if_ed_rtl80x9.c revision 175006
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: head/sys/dev/ed/if_ed_rtl80x9.c 175006 2007-12-31 03:27:21Z imp $");
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
119150957Simp	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_3 | ED_CR_STP);
120150957Simp
121150957Simp	switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) & ED_RTL80X9_CF2_MEDIA) {
122150957Simp	case ED_RTL80X9_CF2_AUTO:
123150957Simp		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO);
124150957Simp		break;
125150957Simp	case ED_RTL80X9_CF2_10_5:
126150957Simp		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_5);
127150957Simp		break;
128150957Simp	case ED_RTL80X9_CF2_10_2:
129150957Simp		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_2);
130150957Simp		break;
131150957Simp	case ED_RTL80X9_CF2_10_T:
132150957Simp		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T |
133151299Simp		    ((ed_nic_inb(sc, ED_RTL80X9_CONFIG3)
134151299Simp		    & ED_RTL80X9_CF3_FUDUP) ? IFM_FDX : 0));
135150957Simp		break;
136150957Simp	}
137150957Simp	return (0);
138150957Simp}
139150957Simp
140150957Simpstatic int
141150957Simped_rtl_set_media(struct ifnet *ifp)
142150957Simp{
143150957Simp	struct ed_softc *sc;
144150957Simp
145150957Simp	sc = ifp->if_softc;
146150957Simp	ED_LOCK(sc);
147150957Simp	ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_3
148150957Simp		| (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_STA | ED_CR_STP)));
149150957Simp
150150957Simp	switch(IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) {
151150957Simp	case IFM_10_T:
152150957Simp		ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_T
153150957Simp			| (ed_nic_inb(sc, ED_RTL80X9_CONFIG2)
154150957Simp				& ~ED_RTL80X9_CF2_MEDIA));
155150957Simp		break;
156150957Simp	case IFM_10_2:
157150957Simp		ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_2
158150957Simp			| (ed_nic_inb(sc, ED_RTL80X9_CONFIG2)
159150957Simp				& ~ED_RTL80X9_CF2_MEDIA));
160150957Simp		break;
161150957Simp	case IFM_10_5:
162150957Simp		ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_5
163150957Simp			| (ed_nic_inb(sc, ED_RTL80X9_CONFIG2)
164150957Simp				& ~ED_RTL80X9_CF2_MEDIA));
165150957Simp		break;
166150957Simp	case IFM_AUTO:
167150957Simp		ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_AUTO
168150957Simp			| (ed_nic_inb(sc, ED_RTL80X9_CONFIG2)
169150957Simp				& ~ED_RTL80X9_CF2_MEDIA));
170150957Simp		break;
171150957Simp	}
172150957Simp	ed_nic_outb(sc, ED_RTL80X9_CONFIG3,
173150957Simp		(sc->ifmedia.ifm_cur->ifm_media & IFM_FDX) ?
174150957Simp		(ed_nic_inb(sc, ED_RTL80X9_CONFIG3) | ED_RTL80X9_CF3_FUDUP) :
175150957Simp		(ed_nic_inb(sc, ED_RTL80X9_CONFIG3) & ~ED_RTL80X9_CF3_FUDUP));
176150957Simp
177150957Simp	ED_UNLOCK(sc);
178150957Simp	return (0);
179150957Simp}
180150957Simp
181150957Simpstatic void
182150957Simped_rtl_get_media(struct ifnet *ifp, struct ifmediareq *imr)
183150957Simp{
184150957Simp	struct ed_softc *sc;
185150957Simp
186150957Simp	sc = ifp->if_softc;
187150957Simp	imr->ifm_active = sc->ifmedia.ifm_cur->ifm_media;
188150957Simp
189150957Simp
190150957Simp	if (IFM_SUBTYPE(imr->ifm_active) == IFM_AUTO) {
191150957Simp		ED_LOCK(sc);
192150957Simp		ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_3 |
193150957Simp			(ed_nic_inb(sc, ED_P0_CR) & (ED_CR_STA | ED_CR_STP)));
194150957Simp
195150957Simp		switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG0)
196175006Simp				& (sc->chip_type == ED_CHIP_TYPE_RTL8029 ? ED_RTL80X9_CF0_BNC
197150957Simp				: (ED_RTL80X9_CF0_AUI | ED_RTL80X9_CF0_BNC))) {
198150957Simp		case ED_RTL80X9_CF0_BNC:
199150957Simp			imr->ifm_active |= IFM_10_2;
200150957Simp			break;
201150957Simp		case ED_RTL80X9_CF0_AUI:
202150957Simp			imr->ifm_active |= IFM_10_5;
203150957Simp			break;
204150957Simp		default:
205150957Simp			imr->ifm_active |= IFM_10_T;
206150957Simp			break;
207150957Simp		}
208150957Simp		ED_UNLOCK(sc);
209150957Simp	}
210150957Simp	imr->ifm_status = 0;
211150957Simp}
212150957Simp
213