The on-board Ethernet interface on DEC 3000 systems (except for models
300) has both a 10base5 and a 10baseT connector, which is software
selected.

The following diff, based upon sparc le@ledma attachment, lets the user
force a specific media regardless of the PROM settings, and will also,
when in 'autoselect' mode, alternate between medias when career is lost.

Tested on 3000/600 (both connectors) and 3000/300LX (10baseT only). This
has zero impact on Ethernet TURBOchannel boards, which use a different
attachment.

Index: dev/tc/if_le_ioasic.c
===================================================================
RCS file: /OpenBSD/src/sys/dev/tc/if_le_ioasic.c,v
retrieving revision 1.17
diff -u -p -r1.17 if_le_ioasic.c
--- dev/tc/if_le_ioasic.c       22 Dec 2014 02:28:52 -0000      1.17
+++ dev/tc/if_le_ioasic.c       22 Sep 2017 20:59:34 -0000
@@ -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 la
 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, 
        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_sof
                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__ */
Index: dev/tc/ioasicreg.h
===================================================================
RCS file: /OpenBSD/src/sys/dev/tc/ioasicreg.h,v
retrieving revision 1.2
diff -u -p -r1.2 ioasicreg.h
--- dev/tc/ioasicreg.h  2 Jun 2003 23:28:04 -0000       1.2
+++ dev/tc/ioasicreg.h  22 Sep 2017 20:59:34 -0000
@@ -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 */

Reply via email to