1 /* $NetBSD: rtl80x9.c,v 1.7 2001/07/08 17:52:02 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/mbuf.h> 43 #include <sys/syslog.h> 44 #include <sys/socket.h> 45 #include <sys/device.h> 46 47 #include <net/if.h> 48 #include <net/if_ether.h> 49 #include <net/if_media.h> 50 51 #include <machine/bus.h> 52 #include <machine/intr.h> 53 54 #include <dev/ic/dp8390reg.h> 55 #include <dev/ic/dp8390var.h> 56 57 #include <dev/ic/ne2000reg.h> 58 #include <dev/ic/ne2000var.h> 59 60 #include <dev/ic/rtl80x9reg.h> 61 #include <dev/ic/rtl80x9var.h> 62 63 int 64 rtl80x9_mediachange(dsc) 65 struct dp8390_softc *dsc; 66 { 67 68 /* 69 * Current media is already set up. Just reset the interface 70 * to let the new value take hold. The new media will be 71 * set up in ne_pci_rtl8029_init_card() called via dp8390_init(). 72 */ 73 dp8390_reset(dsc); 74 return (0); 75 } 76 77 void 78 rtl80x9_mediastatus(sc, ifmr) 79 struct dp8390_softc *sc; 80 struct ifmediareq *ifmr; 81 { 82 struct ifnet *ifp = &sc->sc_ec.ec_if; 83 u_int8_t cr_proto = sc->cr_proto | 84 ((ifp->if_flags & IFF_RUNNING) ? ED_CR_STA : ED_CR_STP); 85 86 /* 87 * Sigh, can detect which media is being used, but can't 88 * detect if we have link or not. 89 */ 90 91 /* Set NIC to page 3 registers. */ 92 NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_CR, cr_proto | ED_CR_PAGE_3); 93 94 if (NIC_GET(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG0) & 95 RTL3_CONFIG0_BNC) 96 ifmr->ifm_active = IFM_ETHER|IFM_10_2; 97 else { 98 ifmr->ifm_active = IFM_ETHER|IFM_10_T; 99 if (NIC_GET(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG3) & 100 RTL3_CONFIG3_FUDUP) 101 ifmr->ifm_active |= IFM_FDX; 102 } 103 104 /* Set NIC to page 0 registers. */ 105 NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_CR, cr_proto | ED_CR_PAGE_0); 106 } 107 108 void 109 rtl80x9_init_card(sc) 110 struct dp8390_softc *sc; 111 { 112 struct ifmedia *ifm = &sc->sc_media; 113 struct ifnet *ifp = &sc->sc_ec.ec_if; 114 u_int8_t cr_proto = sc->cr_proto | 115 ((ifp->if_flags & IFF_RUNNING) ? ED_CR_STA : ED_CR_STP); 116 u_int8_t reg; 117 118 /* Set NIC to page 3 registers. */ 119 NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_CR, cr_proto | ED_CR_PAGE_3); 120 121 /* write enable config1-3. */ 122 NIC_PUT(sc->sc_regt, sc->sc_regh, NERTL_RTL3_EECR, 123 RTL3_EECR_EEM1|RTL3_EECR_EEM0); 124 125 /* First, set basic media type. */ 126 reg = NIC_GET(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG2); 127 reg &= ~(RTL3_CONFIG2_PL1|RTL3_CONFIG2_PL0); 128 switch (IFM_SUBTYPE(ifm->ifm_cur->ifm_media)) { 129 case IFM_AUTO: 130 /* Nothing to do; both bits clear == auto-detect. */ 131 break; 132 133 case IFM_10_T: 134 /* 135 * According to docs, this should be: 136 * reg |= RTL3_CONFIG2_PL0; 137 * but this doesn't work, so make it the same as AUTO. 138 */ 139 break; 140 141 case IFM_10_2: 142 reg |= RTL3_CONFIG2_PL1|RTL3_CONFIG2_PL0; 143 break; 144 } 145 NIC_PUT(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG2, reg); 146 147 /* Now, set duplex mode. */ 148 reg = NIC_GET(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG3); 149 if (ifm->ifm_cur->ifm_media & IFM_FDX) 150 reg |= RTL3_CONFIG3_FUDUP; 151 else 152 reg &= ~RTL3_CONFIG3_FUDUP; 153 NIC_PUT(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG3, reg); 154 155 /* write disable config1-3 */ 156 NIC_PUT(sc->sc_regt, sc->sc_regh, NERTL_RTL3_EECR, 0); 157 158 /* Set NIC to page 0 registers. */ 159 NIC_PUT(sc->sc_regt, sc->sc_regh, ED_P0_CR, cr_proto | ED_CR_PAGE_0); 160 } 161 162 void 163 rtl80x9_media_init(sc) 164 struct dp8390_softc *sc; 165 { 166 static int rtl80x9_media[] = { 167 IFM_ETHER|IFM_AUTO, 168 IFM_ETHER|IFM_10_T, 169 IFM_ETHER|IFM_10_T|IFM_FDX, 170 IFM_ETHER|IFM_10_2, 171 }; 172 static const int rtl80x9_nmedia = 173 sizeof(rtl80x9_media) / sizeof(rtl80x9_media[0]); 174 175 int i, defmedia; 176 u_int8_t conf2, conf3; 177 178 printf("%s: 10base2, 10baseT, 10baseT-FDX, auto, default ", 179 sc->sc_dev.dv_xname); 180 181 bus_space_write_1(sc->sc_regt, sc->sc_regh, ED_P0_CR, ED_CR_PAGE_3); 182 183 conf2 = bus_space_read_1(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG2); 184 conf3 = bus_space_read_1(sc->sc_regt, sc->sc_regh, NERTL_RTL3_CONFIG3); 185 printf("[0x%02x 0x%02x] ", conf2, conf3); 186 187 conf2 &= RTL3_CONFIG2_PL1|RTL3_CONFIG2_PL0; 188 189 switch (conf2) { 190 case 0: 191 defmedia = IFM_ETHER|IFM_AUTO; 192 printf("auto\n"); 193 break; 194 195 case RTL3_CONFIG2_PL1|RTL3_CONFIG2_PL0: 196 case RTL3_CONFIG2_PL1: /* XXX rtl docs sys 10base5, but chip cant do */ 197 defmedia = IFM_ETHER|IFM_10_2; 198 printf("10base2\n"); 199 break; 200 201 case RTL3_CONFIG2_PL0: 202 if (conf3 & RTL3_CONFIG3_FUDUP) { 203 defmedia = IFM_ETHER|IFM_10_T|IFM_FDX; 204 printf("10baseT-FDX\n"); 205 } else { 206 defmedia = IFM_ETHER|IFM_10_T; 207 printf("10baseT\n"); 208 } 209 break; 210 } 211 212 bus_space_write_1(sc->sc_regt, sc->sc_regh, ED_P0_CR, ED_CR_PAGE_0); 213 214 ifmedia_init(&sc->sc_media, 0, dp8390_mediachange, dp8390_mediastatus); 215 for (i = 0; i < rtl80x9_nmedia; i++) 216 ifmedia_add(&sc->sc_media, rtl80x9_media[i], 0, NULL); 217 ifmedia_set(&sc->sc_media, defmedia); 218 } 219