1150957Simp/*- 2150957Simp * Copyright (c) 2003, David Madole 3150957Simp * All rights reserved. 4150957Simp * Copyright (c) 2005, M. Warner Losh. 5150957Simp * All rights reserved. 6150957Simp * 7150957Simp * Redistribution and use in source and binary forms, with or without 8150957Simp * modification, are permitted provided that the following conditions 9150957Simp * are met: 10150957Simp * 1. Redistributions of source code must retain the above copyright 11150957Simp * notice unmodified, this list of conditions, and the following 12150957Simp * disclaimer. 13150957Simp * 2. Redistributions in binary form must reproduce the above copyright 14150957Simp * notice, this list of conditions and the following disclaimer in the 15150957Simp * documentation and/or other materials provided with the distribution. 16150957Simp * 17150957Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18150957Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19150957Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20150957Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21150957Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22150957Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23150957Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24150957Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25150957Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26150957Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27150957Simp * SUCH DAMAGE. 28150957Simp * 29150957Simp * Based on patches subitted by: David Madole, edited by M. Warner Losh. 30150957Simp */ 31150957Simp 32150957Simp 33150957Simp#include <sys/cdefs.h> 34150957Simp__FBSDID("$FreeBSD$"); 35150957Simp 36150957Simp#include "opt_ed.h" 37150957Simp 38150957Simp#include <sys/param.h> 39150957Simp#include <sys/systm.h> 40150957Simp#include <sys/sockio.h> 41150957Simp#include <sys/mbuf.h> 42150957Simp#include <sys/kernel.h> 43150957Simp#include <sys/socket.h> 44150957Simp#include <sys/syslog.h> 45150957Simp 46150957Simp#include <sys/bus.h> 47150957Simp 48150957Simp#include <machine/bus.h> 49150957Simp#include <sys/rman.h> 50150957Simp#include <machine/resource.h> 51150957Simp 52150957Simp#include <net/ethernet.h> 53150957Simp#include <net/if.h> 54150957Simp#include <net/if_arp.h> 55150957Simp#include <net/if_dl.h> 56150957Simp#include <net/if_mib.h> 57150957Simp#include <net/if_media.h> 58150957Simp 59150957Simp#include <net/bpf.h> 60150957Simp 61150957Simp#include <dev/ed/if_edreg.h> 62150957Simp#include <dev/ed/if_edvar.h> 63150957Simp#include <dev/ed/rtl80x9reg.h> 64150957Simp 65150957Simpstatic int ed_rtl_set_media(struct ifnet *ifp); 66150957Simpstatic void ed_rtl_get_media(struct ifnet *ifp, struct ifmediareq *); 67150957Simp 68150957Simpstatic int 69150957Simped_rtl80x9_media_ioctl(struct ed_softc *sc, struct ifreq *ifr, u_long command) 70150957Simp{ 71150957Simp return (ifmedia_ioctl(sc->ifp, ifr, &sc->ifmedia, command)); 72150957Simp} 73150957Simp 74150957Simpint 75150957Simped_probe_RTL80x9(device_t dev, int port_rid, int flags) 76150957Simp{ 77150957Simp struct ed_softc *sc = device_get_softc(dev); 78151299Simp char *ts; 79150957Simp int error; 80150957Simp 81150957Simp if ((error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS))) 82150957Simp return (error); 83151547Simp 84151547Simp sc->asic_offset = ED_NOVELL_ASIC_OFFSET; 85151547Simp sc->nic_offset = ED_NOVELL_NIC_OFFSET; 86150957Simp 87150957Simp if (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_PS0 | ED_CR_PS1)) 88150957Simp ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP); 89150957Simp 90150957Simp if (ed_nic_inb(sc, ED_RTL80X9_80X9ID0) != ED_RTL80X9_ID0) 91150957Simp return (ENXIO); 92150957Simp 93150957Simp switch (ed_nic_inb(sc, ED_RTL80X9_80X9ID1)) { 94150957Simp case ED_RTL8019_ID1: 95150957Simp sc->chip_type = ED_CHIP_TYPE_RTL8019; 96151299Simp ts = "RTL8019"; 97150957Simp break; 98150957Simp case ED_RTL8029_ID1: 99150957Simp sc->chip_type = ED_CHIP_TYPE_RTL8029; 100151299Simp ts = "RTL8029"; 101150957Simp break; 102150957Simp default: 103150957Simp return (ENXIO); 104150957Simp } 105150957Simp 106150957Simp if ((error = ed_probe_Novell_generic(dev, flags))) 107150957Simp return (error); 108150957Simp 109151299Simp sc->type_str = ts; 110150957Simp sc->sc_media_ioctl = &ed_rtl80x9_media_ioctl; 111150957Simp ifmedia_init(&sc->ifmedia, 0, ed_rtl_set_media, ed_rtl_get_media); 112150957Simp 113150957Simp ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_FDX, 0, 0); 114150957Simp ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T, 0, 0); 115150957Simp ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_2, 0, 0); 116150957Simp ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_5, 0, 0); 117150957Simp ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_AUTO, 0, 0); 118150957Simp 119264943Smarius ed_nic_barrier(sc, ED_P0_CR, 1, 120264943Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 121150957Simp ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_3 | ED_CR_STP); 122264943Smarius ed_nic_barrier(sc, ED_P0_CR, 1, 123264943Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 124150957Simp 125150957Simp switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) & ED_RTL80X9_CF2_MEDIA) { 126150957Simp case ED_RTL80X9_CF2_AUTO: 127150957Simp ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO); 128150957Simp break; 129150957Simp case ED_RTL80X9_CF2_10_5: 130150957Simp ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_5); 131150957Simp break; 132150957Simp case ED_RTL80X9_CF2_10_2: 133150957Simp ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_2); 134150957Simp break; 135150957Simp case ED_RTL80X9_CF2_10_T: 136150957Simp ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T | 137151299Simp ((ed_nic_inb(sc, ED_RTL80X9_CONFIG3) 138151299Simp & ED_RTL80X9_CF3_FUDUP) ? IFM_FDX : 0)); 139150957Simp break; 140150957Simp } 141150957Simp return (0); 142150957Simp} 143150957Simp 144150957Simpstatic int 145150957Simped_rtl_set_media(struct ifnet *ifp) 146150957Simp{ 147150957Simp struct ed_softc *sc; 148150957Simp 149150957Simp sc = ifp->if_softc; 150150957Simp ED_LOCK(sc); 151264943Smarius ed_nic_barrier(sc, ED_P0_CR, 1, 152264943Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 153150957Simp ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_3 154150957Simp | (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_STA | ED_CR_STP))); 155264943Smarius ed_nic_barrier(sc, ED_P0_CR, 1, 156264943Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 157150957Simp 158150957Simp switch(IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) { 159150957Simp case IFM_10_T: 160150957Simp ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_T 161150957Simp | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) 162150957Simp & ~ED_RTL80X9_CF2_MEDIA)); 163150957Simp break; 164150957Simp case IFM_10_2: 165150957Simp ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_2 166150957Simp | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) 167150957Simp & ~ED_RTL80X9_CF2_MEDIA)); 168150957Simp break; 169150957Simp case IFM_10_5: 170150957Simp ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_5 171150957Simp | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) 172150957Simp & ~ED_RTL80X9_CF2_MEDIA)); 173150957Simp break; 174150957Simp case IFM_AUTO: 175150957Simp ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_AUTO 176150957Simp | (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) 177150957Simp & ~ED_RTL80X9_CF2_MEDIA)); 178150957Simp break; 179150957Simp } 180150957Simp ed_nic_outb(sc, ED_RTL80X9_CONFIG3, 181150957Simp (sc->ifmedia.ifm_cur->ifm_media & IFM_FDX) ? 182150957Simp (ed_nic_inb(sc, ED_RTL80X9_CONFIG3) | ED_RTL80X9_CF3_FUDUP) : 183150957Simp (ed_nic_inb(sc, ED_RTL80X9_CONFIG3) & ~ED_RTL80X9_CF3_FUDUP)); 184150957Simp 185150957Simp ED_UNLOCK(sc); 186150957Simp return (0); 187150957Simp} 188150957Simp 189150957Simpstatic void 190150957Simped_rtl_get_media(struct ifnet *ifp, struct ifmediareq *imr) 191150957Simp{ 192150957Simp struct ed_softc *sc; 193150957Simp 194150957Simp sc = ifp->if_softc; 195150957Simp imr->ifm_active = sc->ifmedia.ifm_cur->ifm_media; 196150957Simp 197150957Simp 198150957Simp if (IFM_SUBTYPE(imr->ifm_active) == IFM_AUTO) { 199150957Simp ED_LOCK(sc); 200264943Smarius ed_nic_barrier(sc, ED_P0_CR, 1, 201264943Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 202150957Simp ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_3 | 203150957Simp (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_STA | ED_CR_STP))); 204264943Smarius ed_nic_barrier(sc, ED_P0_CR, 1, 205264943Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 206150957Simp 207150957Simp switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG0) 208175006Simp & (sc->chip_type == ED_CHIP_TYPE_RTL8029 ? ED_RTL80X9_CF0_BNC 209150957Simp : (ED_RTL80X9_CF0_AUI | ED_RTL80X9_CF0_BNC))) { 210150957Simp case ED_RTL80X9_CF0_BNC: 211150957Simp imr->ifm_active |= IFM_10_2; 212150957Simp break; 213150957Simp case ED_RTL80X9_CF0_AUI: 214150957Simp imr->ifm_active |= IFM_10_5; 215150957Simp break; 216150957Simp default: 217150957Simp imr->ifm_active |= IFM_10_T; 218150957Simp break; 219150957Simp } 220150957Simp ED_UNLOCK(sc); 221150957Simp } 222150957Simp imr->ifm_status = 0; 223150957Simp} 224150957Simp 225