summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2017-10-13 08:58:43 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2017-10-13 08:58:43 +0000
commit7dc873dc317866d4576d36547c0ae51c9c531001 (patch)
treeb1f4cc0f3f6a12cd3a56195201a5015c3ae12e9e /sys/dev
parentddfce428f37f41b5ffc58370e4bb47f69b96bae9 (diff)
Implement media auto selection for DEC 3000.
diff from miod@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/tc/if_le_ioasic.c128
-rw-r--r--sys/dev/tc/ioasicreg.h3
2 files changed, 129 insertions, 2 deletions
diff --git a/sys/dev/tc/if_le_ioasic.c b/sys/dev/tc/if_le_ioasic.c
index a7a87ecca8e..89a1e368f87 100644
--- a/sys/dev/tc/if_le_ioasic.c
+++ b/sys/dev/tc/if_le_ioasic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_le_ioasic.c,v 1.17 2014/12/22 02:28:52 tedu Exp $ */
+/* $OpenBSD: if_le_ioasic.c,v 1.18 2017/10/13 08:58:42 mpi Exp $ */
/* $NetBSD: if_le_ioasic.c,v 1.18 2001/11/13 06:26:10 lukem Exp $ */
/*
@@ -55,6 +55,10 @@
#include <dev/tc/ioasicreg.h>
#include <dev/tc/ioasicvar.h>
+#ifdef __alpha__
+#include <machine/rpb.h>
+#endif /* __alpha__ */
+
struct le_ioasic_softc {
struct am7990_softc sc_am7990; /* glue to MI code */
struct lereg1 *sc_r1; /* LANCE registers */
@@ -77,6 +81,14 @@ void le_ioasic_copytobuf_gap16(struct lance_softc *, void *, int, int);
void le_ioasic_copyfrombuf_gap16(struct lance_softc *, void *, int, int);
void le_ioasic_zerobuf_gap16(struct lance_softc *, int, int);
+#ifdef __alpha__
+#ifdef DEC_3000_500
+int le_ioasic_ifmedia_change(struct lance_softc *);
+void le_ioasic_ifmedia_status(struct lance_softc *, struct ifmediareq *);
+void le_ioasic_nocarrier(struct lance_softc *);
+#endif
+#endif /* __alpha__ */
+
int
le_ioasic_match(struct device *parent, void *match, void *aux)
{
@@ -155,6 +167,27 @@ le_ioasic_attach(struct device *parent, struct device *self, void *aux)
le->sc_copyfrombuf = le_ioasic_copyfrombuf_gap16;
le->sc_zerobuf = le_ioasic_zerobuf_gap16;
+#ifdef __alpha__
+#ifdef DEC_3000_500
+ /*
+ * On non-300 DEC 3000 models, both AUI and UTP are available.
+ */
+ if (cputype == ST_DEC_3000_500) {
+ static const uint64_t media[] = {
+ IFM_ETHER | IFM_10_T,
+ IFM_ETHER | IFM_10_5,
+ IFM_ETHER | IFM_AUTO
+ };
+ le->sc_mediachange = le_ioasic_ifmedia_change;
+ le->sc_mediastatus = le_ioasic_ifmedia_status;
+ le->sc_supmedia = media;
+ le->sc_nsupmedia = nitems(media);
+ le->sc_defaultmedia = IFM_ETHER | IFM_AUTO;
+ le->sc_nocarrier = le_ioasic_nocarrier;
+ }
+#endif
+#endif /* __alpha__ */
+
dec_le_common_attach(&sc->sc_am7990,
(u_char *)((struct ioasic_softc *)parent)->sc_base
+ IOASIC_SLOT_2_START);
@@ -414,3 +447,96 @@ le_ioasic_zerobuf_gap16(struct lance_softc *sc, int boff, int len)
xfer = min(len, 16);
}
}
+
+#ifdef __alpha__
+#ifdef DEC_3000_500
+int
+le_ioasic_ifmedia_change(struct lance_softc *lsc)
+{
+ struct le_ioasic_softc *sc = (struct le_ioasic_softc *)lsc;
+ struct ifmedia *ifm = &sc->sc_am7990.lsc.sc_ifmedia;
+ bus_space_tag_t ioasic_bst =
+ ((struct ioasic_softc *)sc->sc_am7990.lsc.sc_dev.dv_parent)->sc_bst;
+ bus_space_handle_t ioasic_bsh =
+ ((struct ioasic_softc *)sc->sc_am7990.lsc.sc_dev.dv_parent)->sc_bsh;
+ u_int32_t ossr, ssr;
+
+ if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
+ return EINVAL;
+
+ ossr = ssr = bus_space_read_4(ioasic_bst, ioasic_bsh, IOASIC_CSR);
+
+ switch (IFM_SUBTYPE(ifm->ifm_media)) {
+ case IFM_10_5:
+ ssr &= ~IOASIC_CSR_ETHERNET_UTP;
+ break;
+ case IFM_10_T:
+ ssr |= IOASIC_CSR_ETHERNET_UTP;
+ break;
+ case IFM_AUTO:
+ break;
+ default:
+ return EINVAL;
+ }
+
+ if (ossr != ssr)
+ bus_space_write_4(ioasic_bst, ioasic_bsh, IOASIC_CSR, ssr);
+
+ return 0;
+}
+
+void
+le_ioasic_ifmedia_status(struct lance_softc *lsc, struct ifmediareq *req)
+{
+ struct le_ioasic_softc *sc = (struct le_ioasic_softc *)lsc;
+ bus_space_tag_t ioasic_bst =
+ ((struct ioasic_softc *)sc->sc_am7990.lsc.sc_dev.dv_parent)->sc_bst;
+ bus_space_handle_t ioasic_bsh =
+ ((struct ioasic_softc *)sc->sc_am7990.lsc.sc_dev.dv_parent)->sc_bsh;
+ u_int32_t ssr;
+
+ ssr = bus_space_read_4(ioasic_bst, ioasic_bsh, IOASIC_CSR);
+
+ if (ssr & IOASIC_CSR_ETHERNET_UTP)
+ req->ifm_active = IFM_ETHER | IFM_10_T;
+ else
+ req->ifm_active = IFM_ETHER | IFM_10_5;
+}
+
+void
+le_ioasic_nocarrier(struct lance_softc *lsc)
+{
+ struct le_ioasic_softc *sc = (struct le_ioasic_softc *)lsc;
+ bus_space_tag_t ioasic_bst =
+ ((struct ioasic_softc *)sc->sc_am7990.lsc.sc_dev.dv_parent)->sc_bst;
+ bus_space_handle_t ioasic_bsh =
+ ((struct ioasic_softc *)sc->sc_am7990.lsc.sc_dev.dv_parent)->sc_bsh;
+ u_int32_t ossr, ssr;
+
+ ossr = ssr = bus_space_read_4(ioasic_bst, ioasic_bsh, IOASIC_CSR);
+
+ if (ssr & IOASIC_CSR_ETHERNET_UTP) {
+ switch (IFM_SUBTYPE(lsc->sc_ifmedia.ifm_media)) {
+ case IFM_10_5:
+ case IFM_AUTO:
+ printf("%s: lost carrier on UTP port"
+ ", switching to AUI port\n", lsc->sc_dev.dv_xname);
+ ssr ^= IOASIC_CSR_ETHERNET_UTP;
+ break;
+ }
+ } else {
+ switch (IFM_SUBTYPE(lsc->sc_ifmedia.ifm_media)) {
+ case IFM_10_T:
+ case IFM_AUTO:
+ printf("%s: lost carrier on AUI port"
+ ", switching to UTP port\n", lsc->sc_dev.dv_xname);
+ ssr ^= IOASIC_CSR_ETHERNET_UTP;
+ break;
+ }
+ }
+
+ if (ossr != ssr)
+ bus_space_write_4(ioasic_bst, ioasic_bsh, IOASIC_CSR, ssr);
+}
+#endif
+#endif /* __alpha__ */
diff --git a/sys/dev/tc/ioasicreg.h b/sys/dev/tc/ioasicreg.h
index 9e9ef08ad5e..d71b08605b0 100644
--- a/sys/dev/tc/ioasicreg.h
+++ b/sys/dev/tc/ioasicreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ioasicreg.h,v 1.2 2003/06/02 23:28:04 millert Exp $ */
+/* $OpenBSD: ioasicreg.h,v 1.3 2017/10/13 08:58:42 mpi Exp $ */
/* $NetBSD: ioasicreg.h,v 1.6 2000/07/17 02:18:17 thorpej Exp $ */
/*
@@ -138,6 +138,7 @@
#define IOASIC_CSR_DIAGDN 0x00008000 /* rw */
#define IOASIC_CSR_TXDIS_2 0x00004000 /* rw - 3min,3max+ */
#define IOASIC_CSR_TXDIS_1 0x00002000 /* rw - 3min,3max+ */
+#define IOASIC_CSR_ETHERNET_UTP 0x00002000 /* rw - 3000 but 300 */
#define IOASIC_CSR_ISDN_ENABLE 0x00001000 /* rw - 3000/maxine */
#define IOASIC_CSR_SCC_ENABLE 0x00000800 /* rw */
#define IOASIC_CSR_RTC_ENABLE 0x00000400 /* rw */