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