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