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>
54257176Sglebius#include <net/if_var.h>
55150957Simp#include <net/if_arp.h>
56150957Simp#include <net/if_dl.h>
57150957Simp#include <net/if_mib.h>
58150957Simp#include <net/if_media.h>
59150957Simp
60150957Simp#include <net/bpf.h>
61150957Simp
62150957Simp#include <dev/ed/if_edreg.h>
63150957Simp#include <dev/ed/if_edvar.h>
64150957Simp#include <dev/ed/rtl80x9reg.h>
65150957Simp
66150957Simpstatic int	ed_rtl_set_media(struct ifnet *ifp);
67150957Simpstatic void	ed_rtl_get_media(struct ifnet *ifp, struct ifmediareq *);
68150957Simp
69150957Simpstatic int
70150957Simped_rtl80x9_media_ioctl(struct ed_softc *sc, struct ifreq *ifr, u_long command)
71150957Simp{
72150957Simp	return (ifmedia_ioctl(sc->ifp, ifr, &sc->ifmedia, command));
73150957Simp}
74150957Simp
75150957Simpint
76150957Simped_probe_RTL80x9(device_t dev, int port_rid, int flags)
77150957Simp{
78150957Simp	struct ed_softc *sc = device_get_softc(dev);
79151299Simp	char *ts;
80150957Simp	int error;
81150957Simp
82150957Simp	if ((error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS)))
83150957Simp		return (error);
84151547Simp
85151547Simp	sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
86151547Simp	sc->nic_offset  = ED_NOVELL_NIC_OFFSET;
87150957Simp
88150957Simp	if (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_PS0 | ED_CR_PS1))
89150957Simp		ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
90150957Simp
91150957Simp	if (ed_nic_inb(sc, ED_RTL80X9_80X9ID0) != ED_RTL80X9_ID0)
92150957Simp		return (ENXIO);
93150957Simp
94150957Simp	switch (ed_nic_inb(sc, ED_RTL80X9_80X9ID1)) {
95150957Simp	case ED_RTL8019_ID1:
96150957Simp		sc->chip_type = ED_CHIP_TYPE_RTL8019;
97151299Simp		ts = "RTL8019";
98150957Simp		break;
99150957Simp	case ED_RTL8029_ID1:
100150957Simp		sc->chip_type = ED_CHIP_TYPE_RTL8029;
101151299Simp		ts = "RTL8029";
102150957Simp		break;
103150957Simp	default:
104150957Simp		return (ENXIO);
105150957Simp	}
106150957Simp
107150957Simp	if ((error = ed_probe_Novell_generic(dev, flags)))
108150957Simp		return (error);
109150957Simp
110151299Simp	sc->type_str = ts;
111150957Simp	sc->sc_media_ioctl = &ed_rtl80x9_media_ioctl;
112150957Simp	ifmedia_init(&sc->ifmedia, 0, ed_rtl_set_media, ed_rtl_get_media);
113150957Simp
114150957Simp	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T | IFM_FDX, 0, 0);
115150957Simp	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_T, 0, 0);
116150957Simp	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_2, 0, 0);
117150957Simp	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_10_5, 0, 0);
118150957Simp	ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_AUTO, 0, 0);
119150957Simp
120260050Smarius	ed_nic_barrier(sc, ED_P0_CR, 1,
121260050Smarius	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
122150957Simp	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_3 | ED_CR_STP);
123260050Smarius	ed_nic_barrier(sc, ED_P0_CR, 1,
124260050Smarius	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
125150957Simp
126150957Simp	switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG2) & ED_RTL80X9_CF2_MEDIA) {
127150957Simp	case ED_RTL80X9_CF2_AUTO:
128150957Simp		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO);
129150957Simp		break;
130150957Simp	case ED_RTL80X9_CF2_10_5:
131150957Simp		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_5);
132150957Simp		break;
133150957Simp	case ED_RTL80X9_CF2_10_2:
134150957Simp		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_2);
135150957Simp		break;
136150957Simp	case ED_RTL80X9_CF2_10_T:
137150957Simp		ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_10_T |
138151299Simp		    ((ed_nic_inb(sc, ED_RTL80X9_CONFIG3)
139151299Simp		    & ED_RTL80X9_CF3_FUDUP) ? IFM_FDX : 0));
140150957Simp		break;
141150957Simp	}
142150957Simp	return (0);
143150957Simp}
144150957Simp
145150957Simpstatic int
146150957Simped_rtl_set_media(struct ifnet *ifp)
147150957Simp{
148150957Simp	struct ed_softc *sc;
149150957Simp
150150957Simp	sc = ifp->if_softc;
151150957Simp	ED_LOCK(sc);
152260050Smarius	ed_nic_barrier(sc, ED_P0_CR, 1,
153260050Smarius	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
154150957Simp	ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_3
155150957Simp		| (ed_nic_inb(sc, ED_P0_CR) & (ED_CR_STA | ED_CR_STP)));
156260050Smarius	ed_nic_barrier(sc, ED_P0_CR, 1,
157260050Smarius	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
158150957Simp
159150957Simp	switch(IFM_SUBTYPE(sc->ifmedia.ifm_cur->ifm_media)) {
160150957Simp	case IFM_10_T:
161150957Simp		ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_T
162150957Simp			| (ed_nic_inb(sc, ED_RTL80X9_CONFIG2)
163150957Simp				& ~ED_RTL80X9_CF2_MEDIA));
164150957Simp		break;
165150957Simp	case IFM_10_2:
166150957Simp		ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_2
167150957Simp			| (ed_nic_inb(sc, ED_RTL80X9_CONFIG2)
168150957Simp				& ~ED_RTL80X9_CF2_MEDIA));
169150957Simp		break;
170150957Simp	case IFM_10_5:
171150957Simp		ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_10_5
172150957Simp			| (ed_nic_inb(sc, ED_RTL80X9_CONFIG2)
173150957Simp				& ~ED_RTL80X9_CF2_MEDIA));
174150957Simp		break;
175150957Simp	case IFM_AUTO:
176150957Simp		ed_nic_outb(sc, ED_RTL80X9_CONFIG2, ED_RTL80X9_CF2_AUTO
177150957Simp			| (ed_nic_inb(sc, ED_RTL80X9_CONFIG2)
178150957Simp				& ~ED_RTL80X9_CF2_MEDIA));
179150957Simp		break;
180150957Simp	}
181150957Simp	ed_nic_outb(sc, ED_RTL80X9_CONFIG3,
182150957Simp		(sc->ifmedia.ifm_cur->ifm_media & IFM_FDX) ?
183150957Simp		(ed_nic_inb(sc, ED_RTL80X9_CONFIG3) | ED_RTL80X9_CF3_FUDUP) :
184150957Simp		(ed_nic_inb(sc, ED_RTL80X9_CONFIG3) & ~ED_RTL80X9_CF3_FUDUP));
185150957Simp
186150957Simp	ED_UNLOCK(sc);
187150957Simp	return (0);
188150957Simp}
189150957Simp
190150957Simpstatic void
191150957Simped_rtl_get_media(struct ifnet *ifp, struct ifmediareq *imr)
192150957Simp{
193150957Simp	struct ed_softc *sc;
194150957Simp
195150957Simp	sc = ifp->if_softc;
196150957Simp	imr->ifm_active = sc->ifmedia.ifm_cur->ifm_media;
197150957Simp
198150957Simp
199150957Simp	if (IFM_SUBTYPE(imr->ifm_active) == IFM_AUTO) {
200150957Simp		ED_LOCK(sc);
201260050Smarius		ed_nic_barrier(sc, ED_P0_CR, 1,
202260050Smarius		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
203150957Simp		ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_PAGE_3 |
204150957Simp			(ed_nic_inb(sc, ED_P0_CR) & (ED_CR_STA | ED_CR_STP)));
205260050Smarius		ed_nic_barrier(sc, ED_P0_CR, 1,
206260050Smarius		    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
207150957Simp
208150957Simp		switch (ed_nic_inb(sc, ED_RTL80X9_CONFIG0)
209175006Simp				& (sc->chip_type == ED_CHIP_TYPE_RTL8029 ? ED_RTL80X9_CF0_BNC
210150957Simp				: (ED_RTL80X9_CF0_AUI | ED_RTL80X9_CF0_BNC))) {
211150957Simp		case ED_RTL80X9_CF0_BNC:
212150957Simp			imr->ifm_active |= IFM_10_2;
213150957Simp			break;
214150957Simp		case ED_RTL80X9_CF0_AUI:
215150957Simp			imr->ifm_active |= IFM_10_5;
216150957Simp			break;
217150957Simp		default:
218150957Simp			imr->ifm_active |= IFM_10_T;
219150957Simp			break;
220150957Simp		}
221150957Simp		ED_UNLOCK(sc);
222150957Simp	}
223150957Simp	imr->ifm_status = 0;
224150957Simp}
225150957Simp
226