if_ed_rtl80x9.c revision 330897
1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2003, David Madole 5 * All rights reserved. 6 * Copyright (c) 2005, M. Warner Losh. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice unmodified, this list of conditions, and the following 14 * disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * Based on patches subitted by: David Madole, edited by M. Warner Losh. 32 */ 33 34 35#include <sys/cdefs.h> 36__FBSDID("$FreeBSD: stable/11/sys/dev/ed/if_ed_rtl80x9.c 330897 2018-03-14 03:19:51Z eadler $"); 37 38#include "opt_ed.h" 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/sockio.h> 43#include <sys/mbuf.h> 44#include <sys/kernel.h> 45#include <sys/socket.h> 46#include <sys/syslog.h> 47 48#include <sys/bus.h> 49 50#include <machine/bus.h> 51#include <sys/rman.h> 52#include <machine/resource.h> 53 54#include <net/ethernet.h> 55#include <net/if.h> 56#include <net/if_var.h> 57#include <net/if_arp.h> 58#include <net/if_dl.h> 59#include <net/if_mib.h> 60#include <net/if_media.h> 61 62#include <net/bpf.h> 63 64#include <dev/ed/if_edreg.h> 65#include <dev/ed/if_edvar.h> 66#include <dev/ed/rtl80x9reg.h> 67 68static int ed_rtl_set_media(struct ifnet *ifp); 69static void ed_rtl_get_media(struct ifnet *ifp, struct ifmediareq *); 70 71static int 72ed_rtl80x9_media_ioctl(struct ed_softc *sc, struct ifreq *ifr, u_long command) 73{ 74 return (ifmedia_ioctl(sc->ifp, ifr, &sc->ifmedia, command)); 75} 76 77int 78ed_probe_RTL80x9(device_t dev, int port_rid, int flags) 79{ 80 struct ed_softc *sc = device_get_softc(dev); 81 char *ts; 82 int error; 83 84 if ((error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS))) 85 return (error); 86 87 sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 88 sc->nic_offset = ED_NOVELL_NIC_OFFSET; 89 90 if (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_PS0 | ED_CR_PS1)) 91 ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 92 93 if (ed_nic_inb(sc, ED_RTL80X9_80X9ID0) != ED_RTL80X9_ID0) 94 return (ENXIO); 95 96 switch (ed_nic_inb(sc, ED_RTL80X9_80X9ID1)) { 97 case ED_RTL8019_ID1: 98 sc->chip_type = ED_CHIP_TYPE_RTL8019; 99 ts = "RTL8019"; 100 break; 101 case ED_RTL8029_ID1: 102 sc->chip_type = ED_CHIP_TYPE_RTL8029; 103 ts = "RTL8029"; 104 break; 105 default: 106 return (ENXIO); 107 } 108 109 if ((error = ed_probe_Novell_generic(dev, flags))) 110 return (error); 111 112 sc->type_str = ts; 113 sc->sc_media_ioctl = &ed_rtl80x9_media_ioctl; 114 ifmedia_init(&sc->ifmedia, 0, ed_rtl_set_media, ed_rtl_get_media); 115 116 ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_FDX, 0, 0); 117 ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T, 0, 0); 118 ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_2, 0, 0); 119 ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_5, 0, 0); 120 ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_AUTO, 0, 0); 121 122 ed_nic_barrier(sc, ED_P0_CR, 1, 123 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 124 ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_3 | ED_CR_STP); 125 ed_nic_barrier(sc, ED_P0_CR, 1, 126 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 127 128 switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) & ED_RTL80X9_CF2_MEDIA) { 129 case ED_RTL80X9_CF2_AUTO: 130 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO); 131 break; 132 case ED_RTL80X9_CF2_10_5: 133 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_5); 134 break; 135 case ED_RTL80X9_CF2_10_2: 136 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_2); 137 break; 138 case ED_RTL80X9_CF2_10_T: 139 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T | 140 ((ed_nic_inb(sc, ED_RTL80X9_CONFIG3) 141 & ED_RTL80X9_CF3_FUDUP) ? IFM_FDX : 0)); 142 break; 143 } 144 return (0); 145} 146 147static int 148ed_rtl_set_media(struct ifnet *ifp) 149{ 150 struct ed_softc *sc; 151 152 sc = ifp->if_softc; 153 ED_LOCK(sc); 154 ed_nic_barrier(sc, ED_P0_CR, 1, 155 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 156 ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_3 157 | (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_STA | ED_CR_STP))); 158 ed_nic_barrier(sc, ED_P0_CR, 1, 159 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 160 161 switch(IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) { 162 case IFM_10_T: 163 ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_T 164 | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) 165 & ~ED_RTL80X9_CF2_MEDIA)); 166 break; 167 case IFM_10_2: 168 ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_2 169 | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) 170 & ~ED_RTL80X9_CF2_MEDIA)); 171 break; 172 case IFM_10_5: 173 ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_5 174 | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) 175 & ~ED_RTL80X9_CF2_MEDIA)); 176 break; 177 case IFM_AUTO: 178 ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_AUTO 179 | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) 180 & ~ED_RTL80X9_CF2_MEDIA)); 181 break; 182 } 183 ed_nic_outb(sc, ED_RTL80X9_CONFIG3, 184 (sc->ifmedia.ifm_cur->ifm_media & IFM_FDX) ? 185 (ed_nic_inb(sc, ED_RTL80X9_CONFIG3) | ED_RTL80X9_CF3_FUDUP) : 186 (ed_nic_inb(sc, ED_RTL80X9_CONFIG3) & ~ED_RTL80X9_CF3_FUDUP)); 187 188 ED_UNLOCK(sc); 189 return (0); 190} 191 192static void 193ed_rtl_get_media(struct ifnet *ifp, struct ifmediareq *imr) 194{ 195 struct ed_softc *sc; 196 197 sc = ifp->if_softc; 198 imr->ifm_active = sc->ifmedia.ifm_cur->ifm_media; 199 200 201 if (IFM_SUBTYPE(imr->ifm_active) == IFM_AUTO) { 202 ED_LOCK(sc); 203 ed_nic_barrier(sc, ED_P0_CR, 1, 204 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 205 ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_3 | 206 (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_STA | ED_CR_STP))); 207 ed_nic_barrier(sc, ED_P0_CR, 1, 208 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 209 210 switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG0) 211 & (sc->chip_type == ED_CHIP_TYPE_RTL8029 ? ED_RTL80X9_CF0_BNC 212 : (ED_RTL80X9_CF0_AUI | ED_RTL80X9_CF0_BNC))) { 213 case ED_RTL80X9_CF0_BNC: 214 imr->ifm_active |= IFM_10_2; 215 break; 216 case ED_RTL80X9_CF0_AUI: 217 imr->ifm_active |= IFM_10_5; 218 break; 219 default: 220 imr->ifm_active |= IFM_10_T; 221 break; 222 } 223 ED_UNLOCK(sc); 224 } 225 imr->ifm_status = 0; 226} 227 228