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 */