if_ed_rtl80x9.c revision 257176
1139825Simp/*- 282899Sjake * Copyright (c) 2003, David Madole 382899Sjake * All rights reserved. 482899Sjake * Copyright (c) 2005, M. Warner Losh. 580708Sjake * All rights reserved. 682899Sjake * 782899Sjake * Redistribution and use in source and binary forms, with or without 882899Sjake * modification, are permitted provided that the following conditions 982899Sjake * are met: 1082899Sjake * 1. Redistributions of source code must retain the above copyright 1180708Sjake * notice unmodified, this list of conditions, and the following 1282899Sjake * disclaimer. 1382899Sjake * 2. Redistributions in binary form must reproduce the above copyright 1482899Sjake * notice, this list of conditions and the following disclaimer in the 1580708Sjake * documentation and/or other materials provided with the distribution. 1682899Sjake * 1782899Sjake * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1882899Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1982899Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2082899Sjake * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2182899Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2282899Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2382899Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2482899Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2582899Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2682899Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2780708Sjake * SUCH DAMAGE. 2880708Sjake * 2980708Sjake * Based on patches subitted by: David Madole, edited by M. Warner Losh. 3080708Sjake */ 3180708Sjake 3280708Sjake 3380709Sjake#include <sys/cdefs.h> 3480709Sjake__FBSDID("$FreeBSD: head/sys/dev/ed/if_ed_rtl80x9.c 257176 2013-10-26 17:58:36Z glebius $"); 3580709Sjake 3680709Sjake#include "opt_ed.h" 3780709Sjake 3880709Sjake#include <sys/param.h> 3982004Sjake#include <sys/systm.h> 4080709Sjake#include <sys/sockio.h> 41131952Smarcel#include <sys/mbuf.h> 4280709Sjake#include <sys/kernel.h> 43115970Sjake#include <sys/socket.h> 4480709Sjake#include <sys/syslog.h> 4580709Sjake 4680709Sjake#include <sys/bus.h> 4786525Sjake 48131952Smarcel#include <machine/bus.h> 49131952Smarcel#include <sys/rman.h> 5086525Sjake#include <machine/resource.h> 5180709Sjake 52131952Smarcel#include <net/ethernet.h> 53131952Smarcel#include <net/if.h> 5480709Sjake#include <net/if_var.h> 5580709Sjake#include <net/if_arp.h> 5680709Sjake#include <net/if_dl.h> 5780709Sjake#include <net/if_mib.h> 5880709Sjake#include <net/if_media.h> 5980709Sjake 6080709Sjake#include <net/bpf.h> 6180709Sjake 6280709Sjake#include <dev/ed/if_edreg.h> 6380709Sjake#include <dev/ed/if_edvar.h> 6480709Sjake#include <dev/ed/rtl80x9reg.h> 6580709Sjake 6680709Sjakestatic int ed_rtl_set_media(struct ifnet *ifp); 6780709Sjakestatic void ed_rtl_get_media(struct ifnet *ifp, struct ifmediareq *); 6880709Sjake 6980708Sjakestatic int 70ed_rtl80x9_media_ioctl(struct ed_softc *sc, struct ifreq *ifr, u_long command) 71{ 72 return (ifmedia_ioctl(sc->ifp, ifr, &sc->ifmedia, command)); 73} 74 75int 76ed_probe_RTL80x9(device_t dev, int port_rid, int flags) 77{ 78 struct ed_softc *sc = device_get_softc(dev); 79 char *ts; 80 int error; 81 82 if ((error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS))) 83 return (error); 84 85 sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 86 sc->nic_offset = ED_NOVELL_NIC_OFFSET; 87 88 if (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_PS0 | ED_CR_PS1)) 89 ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 90 91 if (ed_nic_inb(sc, ED_RTL80X9_80X9ID0) != ED_RTL80X9_ID0) 92 return (ENXIO); 93 94 switch (ed_nic_inb(sc, ED_RTL80X9_80X9ID1)) { 95 case ED_RTL8019_ID1: 96 sc->chip_type = ED_CHIP_TYPE_RTL8019; 97 ts = "RTL8019"; 98 break; 99 case ED_RTL8029_ID1: 100 sc->chip_type = ED_CHIP_TYPE_RTL8029; 101 ts = "RTL8029"; 102 break; 103 default: 104 return (ENXIO); 105 } 106 107 if ((error = ed_probe_Novell_generic(dev, flags))) 108 return (error); 109 110 sc->type_str = ts; 111 sc->sc_media_ioctl = &ed_rtl80x9_media_ioctl; 112 ifmedia_init(&sc->ifmedia, 0, ed_rtl_set_media, ed_rtl_get_media); 113 114 ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_FDX, 0, 0); 115 ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T, 0, 0); 116 ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_2, 0, 0); 117 ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_5, 0, 0); 118 ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_AUTO, 0, 0); 119 120 ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_3 | ED_CR_STP); 121 122 switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) & ED_RTL80X9_CF2_MEDIA) { 123 case ED_RTL80X9_CF2_AUTO: 124 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO); 125 break; 126 case ED_RTL80X9_CF2_10_5: 127 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_5); 128 break; 129 case ED_RTL80X9_CF2_10_2: 130 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_2); 131 break; 132 case ED_RTL80X9_CF2_10_T: 133 ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T | 134 ((ed_nic_inb(sc, ED_RTL80X9_CONFIG3) 135 & ED_RTL80X9_CF3_FUDUP) ? IFM_FDX : 0)); 136 break; 137 } 138 return (0); 139} 140 141static int 142ed_rtl_set_media(struct ifnet *ifp) 143{ 144 struct ed_softc *sc; 145 146 sc = ifp->if_softc; 147 ED_LOCK(sc); 148 ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_3 149 | (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_STA | ED_CR_STP))); 150 151 switch(IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) { 152 case IFM_10_T: 153 ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_T 154 | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) 155 & ~ED_RTL80X9_CF2_MEDIA)); 156 break; 157 case IFM_10_2: 158 ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_2 159 | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) 160 & ~ED_RTL80X9_CF2_MEDIA)); 161 break; 162 case IFM_10_5: 163 ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_5 164 | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) 165 & ~ED_RTL80X9_CF2_MEDIA)); 166 break; 167 case IFM_AUTO: 168 ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_AUTO 169 | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) 170 & ~ED_RTL80X9_CF2_MEDIA)); 171 break; 172 } 173 ed_nic_outb(sc, ED_RTL80X9_CONFIG3, 174 (sc->ifmedia.ifm_cur->ifm_media & IFM_FDX) ? 175 (ed_nic_inb(sc, ED_RTL80X9_CONFIG3) | ED_RTL80X9_CF3_FUDUP) : 176 (ed_nic_inb(sc, ED_RTL80X9_CONFIG3) & ~ED_RTL80X9_CF3_FUDUP)); 177 178 ED_UNLOCK(sc); 179 return (0); 180} 181 182static void 183ed_rtl_get_media(struct ifnet *ifp, struct ifmediareq *imr) 184{ 185 struct ed_softc *sc; 186 187 sc = ifp->if_softc; 188 imr->ifm_active = sc->ifmedia.ifm_cur->ifm_media; 189 190 191 if (IFM_SUBTYPE(imr->ifm_active) == IFM_AUTO) { 192 ED_LOCK(sc); 193 ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_3 | 194 (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_STA | ED_CR_STP))); 195 196 switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG0) 197 & (sc->chip_type == ED_CHIP_TYPE_RTL8029 ? ED_RTL80X9_CF0_BNC 198 : (ED_RTL80X9_CF0_AUI | ED_RTL80X9_CF0_BNC))) { 199 case ED_RTL80X9_CF0_BNC: 200 imr->ifm_active |= IFM_10_2; 201 break; 202 case ED_RTL80X9_CF0_AUI: 203 imr->ifm_active |= IFM_10_5; 204 break; 205 default: 206 imr->ifm_active |= IFM_10_T; 207 break; 208 } 209 ED_UNLOCK(sc); 210 } 211 imr->ifm_status = 0; 212} 213 214