if_ed_pccard.c revision 199380
1168404Spjd/*-
2168404Spjd * Copyright (c) 2005, M. Warner Losh
3168404Spjd * Copyright (c) 1995, David Greenman
4168404Spjd * All rights reserved.
5168404Spjd *
6168404Spjd * Redistribution and use in source and binary forms, with or without
7168404Spjd * modification, are permitted provided that the following conditions
8168404Spjd * are met:
9168404Spjd * 1. Redistributions of source code must retain the above copyright
10168404Spjd *    notice unmodified, this list of conditions, and the following
11168404Spjd *    disclaimer.
12168404Spjd * 2. Redistributions in binary form must reproduce the above copyright
13168404Spjd *    notice, this list of conditions and the following disclaimer in the
14168404Spjd *    documentation and/or other materials provided with the distribution.
15168404Spjd *
16168404Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17168404Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18168404Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19168404Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20168404Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21168404Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22185029Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23168404Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24168404Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25168404Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26168404Spjd * SUCH DAMAGE.
27168404Spjd *
28168404Spjd * $FreeBSD: head/sys/dev/ed/if_ed_pccard.c 199380 2009-11-17 14:23:09Z jhb $
29168404Spjd */
30168404Spjd
31168404Spjd/*
32168404Spjd * Notes for adding media support.  Each chipset is somewhat different
33168404Spjd * from the others.  Linux has a table of OIDs that it uses to see what
34168404Spjd * supports the misc register of the NS83903.  But a sampling of datasheets
35168404Spjd * I could dig up on cards I own paints a different picture.
36168404Spjd *
37185029Spjd * Chipset specific details:
38185029Spjd * NS 83903/902A paired
39185029Spjd *    ccr base 0x1020
40168404Spjd *    id register at 0x1000: 7-3 = 0, 2-0 = 1.
41185029Spjd *	(maybe this test is too week)
42168404Spjd *    misc register at 0x018:
43168404Spjd *	6 WAIT_TOUTENABLE enable watchdog timeout
44185029Spjd *	3 AUI/TPI 1 AUX, 0 TPI
45185029Spjd *	2 loopback
46185029Spjd *      1 gdlink (tpi mode only) 1 tp good, 0 tp bad
47185029Spjd *	0 0-no mam, 1 mam connected
48185029Spjd *
49185029Spjd * NS83926 appears to be a NS pcmcia glue chip used on the IBM Ethernet II
50185029Spjd * and the NEC PC9801N-J12 ccr base 0x2000!
51185029Spjd *
52185029Spjd * winbond 289c926
53185029Spjd *    ccr base 0xfd0
54185029Spjd *    cfb (am 0xff2):
55185029Spjd *	0-1 PHY01	00 TPI, 01 10B2, 10 10B5, 11 TPI (reduced squ)
56185029Spjd *	2 LNKEN		0 - enable link and auto switch, 1 disable
57185029Spjd *	3 LNKSTS	TPI + LNKEN=0 + link good == 1, else 0
58185029Spjd *    sr (am 0xff4)
59185029Spjd *	88 00 88 00 88 00, etc
60185029Spjd *
61185029Spjd * TMI tc3299a (cr PHY01 == 0)
62185029Spjd *    ccr base 0x3f8
63185029Spjd *    cra (io 0xa)
64185029Spjd *    crb (io 0xb)
65185029Spjd *	0-1 PHY01	00 auto, 01 res, 10 10B5, 11 TPI
66185029Spjd *	2 GDLINK	1 disable checking of link
67185029Spjd *	6 LINK		0 bad link, 1 good link
68185029Spjd *
69185029Spjd * EN5017A, EN5020	no data, but very popular
70185029Spjd * Other chips?
71185029Spjd * NetBSD supports RTL8019, but none have surfaced that I can see
72185029Spjd */
73185029Spjd
74185029Spjd#include <sys/param.h>
75185029Spjd#include <sys/systm.h>
76185029Spjd#include <sys/socket.h>
77185029Spjd#include <sys/kernel.h>
78185029Spjd#include <sys/conf.h>
79185029Spjd#include <sys/uio.h>
80185029Spjd
81185029Spjd#include <sys/module.h>
82185029Spjd#include <sys/bus.h>
83185029Spjd#include <machine/bus.h>
84185029Spjd#include <sys/rman.h>
85185029Spjd#include <machine/resource.h>
86185029Spjd
87185029Spjd#include <net/ethernet.h>
88185029Spjd#include <net/if.h>
89185029Spjd#include <net/if_arp.h>
90185029Spjd#include <net/if_mib.h>
91185029Spjd#include <net/if_media.h>
92185029Spjd
93185029Spjd#include <dev/ed/if_edreg.h>
94185029Spjd#include <dev/ed/if_edvar.h>
95185029Spjd#include <dev/ed/ax88x90reg.h>
96185029Spjd#include <dev/ed/dl100xxreg.h>
97185029Spjd#include <dev/ed/tc5299jreg.h>
98185029Spjd#include <dev/pccard/pccardvar.h>
99185029Spjd#include <dev/pccard/pccardreg.h>
100185029Spjd#include <dev/pccard/pccard_cis.h>
101185029Spjd#include <dev/mii/mii.h>
102185029Spjd#include <dev/mii/miivar.h>
103185029Spjd
104185029Spjd#include "card_if.h"
105185029Spjd/* "device miibus" required.  See GENERIC if you get errors here. */
106185029Spjd#include "miibus_if.h"
107185029Spjd#include "pccarddevs.h"
108185029Spjd
109185029Spjd/*
110185029Spjd * NE-2000 based PC Cards have a number of ways to get the MAC address.
111185029Spjd * Some cards encode this as a FUNCE.  Others have this in the ROMs the
112185029Spjd * same way that ISA cards do.  Some have it encoded in the attribute
113185029Spjd * memory somewhere that isn't in the CIS.  Some new chipsets have it
114185029Spjd * in special registers in the ASIC part of the chip.
115185029Spjd *
116185029Spjd * For those cards that have the MAC adress stored in attribute memory
117185029Spjd * outside of a FUNCE entry in the CIS, nearly all of them have it at
118185029Spjd * a fixed offset (0xff0).  We use that offset as a source of last
119185029Spjd * resource if other offsets have failed.  This is the address of the
120185029Spjd * National Semiconductor DP83903A, which is the only chip's datasheet
121185029Spjd * I've found.
122185029Spjd */
123185029Spjd#define ED_DEFAULT_MAC_OFFSET	0xff0
124185029Spjd
125185029Spjdstatic const struct ed_product {
126185029Spjd	struct pccard_product	prod;
127185029Spjd	int flags;
128185029Spjd#define	NE2000DVF_DL100XX	0x0001		/* chip is D-Link DL10019/22 */
129185029Spjd#define	NE2000DVF_AX88X90	0x0002		/* chip is ASIX AX88[17]90 */
130185029Spjd#define NE2000DVF_TC5299J	0x0004		/* chip is Tamarack TC5299J */
131185029Spjd#define NE2000DVF_TOSHIBA	0x0008		/* Toshiba DP83902A */
132185029Spjd#define NE2000DVF_ENADDR	0x0100		/* Get MAC from attr mem */
133185029Spjd#define NE2000DVF_ANYFUNC	0x0200		/* Allow any function type */
134185029Spjd#define NE2000DVF_MODEM		0x0400		/* Has a modem/serial */
135185029Spjd	int enoff;
136168404Spjd} ed_pccard_products[] = {
137168404Spjd	{ PCMCIA_CARD(ACCTON, EN2212), 0},
138168404Spjd	{ PCMCIA_CARD(ACCTON, EN2216), 0},
139168404Spjd	{ PCMCIA_CARD(ALLIEDTELESIS, LA_PCM), 0},
140168404Spjd	{ PCMCIA_CARD(AMBICOM, AMB8002), 0},
141168404Spjd	{ PCMCIA_CARD(AMBICOM, AMB8002T), 0},
142185029Spjd	{ PCMCIA_CARD(AMBICOM, AMB8010), 0},
143168404Spjd	{ PCMCIA_CARD(AMBICOM, AMB8010_ALT), 0},
144168404Spjd	{ PCMCIA_CARD(AMBICOM, AMB8610), 0},
145168404Spjd	{ PCMCIA_CARD(BILLIONTON, CFLT10N), 0},
146168404Spjd	{ PCMCIA_CARD(BILLIONTON, LNA100B), NE2000DVF_AX88X90},
147168404Spjd	{ PCMCIA_CARD(BILLIONTON, LNT10TB), 0},
148168404Spjd	{ PCMCIA_CARD(BILLIONTON, LNT10TN), 0},
149168404Spjd	{ PCMCIA_CARD(BROMAX, AXNET), NE2000DVF_AX88X90},
150168404Spjd	{ PCMCIA_CARD(BROMAX, IPORT), 0},
151168404Spjd	{ PCMCIA_CARD(BROMAX, IPORT2), 0},
152168404Spjd	{ PCMCIA_CARD(BUFFALO, LPC2_CLT), 0},
153168404Spjd	{ PCMCIA_CARD(BUFFALO, LPC3_CLT), 0},
154168404Spjd	{ PCMCIA_CARD(BUFFALO, LPC3_CLX), NE2000DVF_AX88X90},
155168404Spjd	{ PCMCIA_CARD(BUFFALO, LPC4_TX), NE2000DVF_AX88X90},
156168404Spjd	{ PCMCIA_CARD(BUFFALO, LPC4_CLX), NE2000DVF_AX88X90},
157168404Spjd	{ PCMCIA_CARD(BUFFALO, LPC_CF_CLT), 0},
158168404Spjd	{ PCMCIA_CARD(CNET, NE2000), 0},
159168404Spjd	{ PCMCIA_CARD(COMPEX, AX88190), NE2000DVF_AX88X90},
160168404Spjd	{ PCMCIA_CARD(COMPEX, LANMODEM), 0},
161168404Spjd	{ PCMCIA_CARD(COMPEX, LINKPORT_ENET_B), 0},
162168404Spjd	{ PCMCIA_CARD(COREGA, ETHER_II_PCC_T), 0},
163168404Spjd	{ PCMCIA_CARD(COREGA, ETHER_II_PCC_TD), 0},
164168404Spjd	{ PCMCIA_CARD(COREGA, ETHER_PCC_T), 0},
165168404Spjd	{ PCMCIA_CARD(COREGA, ETHER_PCC_TD), 0},
166168404Spjd	{ PCMCIA_CARD(COREGA, FAST_ETHER_PCC_TX), NE2000DVF_DL100XX},
167168404Spjd	{ PCMCIA_CARD(COREGA, FETHER_PCC_TXD), NE2000DVF_AX88X90},
168168404Spjd	{ PCMCIA_CARD(COREGA, FETHER_PCC_TXF), NE2000DVF_DL100XX},
169168404Spjd	{ PCMCIA_CARD(COREGA, FETHER_II_PCC_TXD), NE2000DVF_AX88X90},
170168404Spjd	{ PCMCIA_CARD(COREGA, LAPCCTXD), 0},
171168404Spjd	{ PCMCIA_CARD(DAYNA, COMMUNICARD_E_1), 0},
172168404Spjd	{ PCMCIA_CARD(DAYNA, COMMUNICARD_E_2), 0},
173168404Spjd	{ PCMCIA_CARD(DLINK, DE650), NE2000DVF_ANYFUNC },
174168404Spjd	{ PCMCIA_CARD(DLINK, DE660), 0 },
175168404Spjd	{ PCMCIA_CARD(DLINK, DE660PLUS), 0},
176168404Spjd	{ PCMCIA_CARD(DYNALINK, L10C), 0},
177168404Spjd	{ PCMCIA_CARD(EDIMAX, EP4000A), 0},
178168404Spjd	{ PCMCIA_CARD(EPSON, EEN10B), 0},
179168404Spjd	{ PCMCIA_CARD(EXP, THINLANCOMBO), 0},
180168404Spjd	{ PCMCIA_CARD(GLOBALVILLAGE, LANMODEM), 0},
181168404Spjd	{ PCMCIA_CARD(GREY_CELL, TDK3000), 0},
182168404Spjd	{ PCMCIA_CARD(GREY_CELL, DMF650TX),
183168404Spjd	    NE2000DVF_ANYFUNC | NE2000DVF_DL100XX | NE2000DVF_MODEM},
184197150Spjd	{ PCMCIA_CARD(GVC, NIC_2000P), 0},
185168404Spjd	{ PCMCIA_CARD(IBM, HOME_AND_AWAY), 0},
186168404Spjd	{ PCMCIA_CARD(IBM, INFOMOVER), 0},
187168404Spjd	{ PCMCIA_CARD(IODATA3, PCLAT), 0},
188197150Spjd	{ PCMCIA_CARD(KINGSTON, CIO10T), 0},
189168404Spjd	{ PCMCIA_CARD(KINGSTON, KNE2), 0},
190168404Spjd	{ PCMCIA_CARD(LANTECH, FASTNETTX), NE2000DVF_AX88X90},
191168404Spjd	/* Same ID for many different cards, including generic NE2000 */
192168404Spjd	{ PCMCIA_CARD(LINKSYS, COMBO_ECARD),
193168404Spjd	    NE2000DVF_DL100XX | NE2000DVF_AX88X90},
194168404Spjd	{ PCMCIA_CARD(LINKSYS, ECARD_1), 0},
195168404Spjd	{ PCMCIA_CARD(LINKSYS, ECARD_2), 0},
196168404Spjd	{ PCMCIA_CARD(LINKSYS, ETHERFAST), NE2000DVF_DL100XX},
197168404Spjd	{ PCMCIA_CARD(LINKSYS, TRUST_COMBO_ECARD), 0},
198197150Spjd	{ PCMCIA_CARD(MACNICA, ME1_JEIDA), 0},
199197150Spjd	{ PCMCIA_CARD(MAGICRAM, ETHER), 0},
200197150Spjd	{ PCMCIA_CARD(MELCO, LPC3_CLX), NE2000DVF_AX88X90},
201197150Spjd	{ PCMCIA_CARD(MELCO, LPC3_TX), NE2000DVF_AX88X90},
202197150Spjd	{ PCMCIA_CARD(MELCO2, LPC2_T), 0},
203197150Spjd	{ PCMCIA_CARD(MELCO2, LPC2_TX), 0},
204168404Spjd	{ PCMCIA_CARD(MITSUBISHI, B8895), NE2000DVF_ANYFUNC}, /* NG */
205168404Spjd	{ PCMCIA_CARD(MICRORESEARCH, MR10TPC), 0},
206168404Spjd	{ PCMCIA_CARD(NDC, ND5100_E), 0},
207185029Spjd	{ PCMCIA_CARD(NETGEAR, FA410TXC), NE2000DVF_DL100XX},
208168404Spjd	/* Same ID as DLINK DFE-670TXD.  670 has DL10022, fa411 has ax88790 */
209168404Spjd	{ PCMCIA_CARD(NETGEAR, FA411), NE2000DVF_AX88X90 | NE2000DVF_DL100XX},
210168404Spjd	{ PCMCIA_CARD(NEXTCOM, NEXTHAWK), 0},
211168404Spjd	{ PCMCIA_CARD(NEWMEDIA, LANSURFER), NE2000DVF_ANYFUNC},
212185029Spjd	{ PCMCIA_CARD(NEWMEDIA, LIVEWIRE), 0},
213168404Spjd	{ PCMCIA_CARD(OEM2, 100BASE), NE2000DVF_AX88X90},
214185029Spjd	{ PCMCIA_CARD(OEM2, ETHERNET), 0},
215185029Spjd	{ PCMCIA_CARD(OEM2, FAST_ETHERNET), NE2000DVF_AX88X90},
216168404Spjd	{ PCMCIA_CARD(OEM2, NE2000), 0},
217185029Spjd	{ PCMCIA_CARD(PLANET, SMARTCOM2000), 0 },
218168404Spjd	{ PCMCIA_CARD(PREMAX, PE200), 0},
219168404Spjd	{ PCMCIA_CARD(PSION, LANGLOBAL),
220185029Spjd	    NE2000DVF_ANYFUNC | NE2000DVF_AX88X90 | NE2000DVF_MODEM},
221168404Spjd	{ PCMCIA_CARD(RACORE, ETHERNET), 0},
222168404Spjd	{ PCMCIA_CARD(RACORE, FASTENET), NE2000DVF_AX88X90},
223185029Spjd	{ PCMCIA_CARD(RACORE, 8041TX), NE2000DVF_AX88X90 | NE2000DVF_TC5299J},
224168404Spjd	{ PCMCIA_CARD(RELIA, COMBO), 0},
225168404Spjd	{ PCMCIA_CARD(RIOS, PCCARD3), 0},
226168404Spjd	{ PCMCIA_CARD(RPTI, EP400), 0},
227185029Spjd	{ PCMCIA_CARD(RPTI, EP401), 0},
228185029Spjd	{ PCMCIA_CARD(SMC, EZCARD), 0},
229168404Spjd	{ PCMCIA_CARD(SOCKET, EA_ETHER), 0},
230168404Spjd	{ PCMCIA_CARD(SOCKET, ES_1000), 0},
231185029Spjd	{ PCMCIA_CARD(SOCKET, LP_ETHER), 0},
232185029Spjd	{ PCMCIA_CARD(SOCKET, LP_ETHER_CF), 0},
233185029Spjd	{ PCMCIA_CARD(SOCKET, LP_ETH_10_100_CF), NE2000DVF_DL100XX},
234185029Spjd	{ PCMCIA_CARD(SVEC, COMBOCARD), 0},
235168404Spjd	{ PCMCIA_CARD(SVEC, LANCARD), 0},
236168404Spjd	{ PCMCIA_CARD(TAMARACK, ETHERNET), 0},
237168404Spjd	{ PCMCIA_CARD(TDK, CFE_10), 0},
238168404Spjd	{ PCMCIA_CARD(TDK, LAK_CD031), 0},
239168404Spjd	{ PCMCIA_CARD(TDK, DFL5610WS), 0},
240168404Spjd	{ PCMCIA_CARD(TELECOMDEVICE, LM5LT), 0 },
241168404Spjd	{ PCMCIA_CARD(TELECOMDEVICE, TCD_HPC100), NE2000DVF_AX88X90},
242168404Spjd	{ PCMCIA_CARD(TJ, PTJ_LAN_T), 0 },
243168404Spjd	{ PCMCIA_CARD(TOSHIBA2, LANCT00A), NE2000DVF_ANYFUNC | NE2000DVF_TOSHIBA},
244168404Spjd	{ PCMCIA_CARD(ZONET, ZEN), 0},
245168404Spjd	{ { NULL } }
246168404Spjd};
247168404Spjd
248168404Spjd/*
249168404Spjd *      PC Card (PCMCIA) specific code.
250168404Spjd */
251168404Spjdstatic int	ed_pccard_probe(device_t);
252168404Spjdstatic int	ed_pccard_attach(device_t);
253168404Spjdstatic void	ed_pccard_tick(struct ed_softc *);
254168404Spjd
255168404Spjdstatic int	ed_pccard_dl100xx(device_t dev, const struct ed_product *);
256168404Spjdstatic void	ed_pccard_dl100xx_mii_reset(struct ed_softc *sc);
257168404Spjdstatic u_int	ed_pccard_dl100xx_mii_readbits(struct ed_softc *sc, int nbits);
258168404Spjdstatic void	ed_pccard_dl100xx_mii_writebits(struct ed_softc *sc, u_int val,
259168404Spjd    int nbits);
260168404Spjd
261168404Spjdstatic int	ed_pccard_ax88x90(device_t dev, const struct ed_product *);
262168404Spjdstatic u_int	ed_pccard_ax88x90_mii_readbits(struct ed_softc *sc, int nbits);
263168404Spjdstatic void	ed_pccard_ax88x90_mii_writebits(struct ed_softc *sc, u_int val,
264168404Spjd    int nbits);
265168404Spjd
266168404Spjdstatic int	ed_miibus_readreg(device_t dev, int phy, int reg);
267168404Spjdstatic int	ed_ifmedia_upd(struct ifnet *);
268168404Spjdstatic void	ed_ifmedia_sts(struct ifnet *, struct ifmediareq *);
269168404Spjd
270168404Spjdstatic int	ed_pccard_tc5299j(device_t dev, const struct ed_product *);
271168404Spjdstatic u_int	ed_pccard_tc5299j_mii_readbits(struct ed_softc *sc, int nbits);
272168404Spjdstatic void	ed_pccard_tc5299j_mii_writebits(struct ed_softc *sc, u_int val,
273168404Spjd    int nbits);
274168404Spjd
275168404Spjdstatic void
276168404Spjded_pccard_print_entry(const struct ed_product *pp)
277168404Spjd{
278168404Spjd	int i;
279168404Spjd
280168404Spjd	printf("Product entry: ");
281168404Spjd	if (pp->prod.pp_name)
282168404Spjd		printf("name='%s',", pp->prod.pp_name);
283168404Spjd	printf("vendor=%#x,product=%#x", pp->prod.pp_vendor,
284168404Spjd	    pp->prod.pp_product);
285168404Spjd	for (i = 0; i < 4; i++)
286168404Spjd		if (pp->prod.pp_cis[i])
287168404Spjd			printf(",CIS%d='%s'", i, pp->prod.pp_cis[i]);
288168404Spjd	printf("\n");
289168404Spjd}
290168404Spjd
291168404Spjdstatic int
292168404Spjded_pccard_probe(device_t dev)
293168404Spjd{
294168404Spjd	const struct ed_product *pp, *pp2;
295168404Spjd	int		error, first = 1;
296168404Spjd	uint32_t	fcn = PCCARD_FUNCTION_UNSPEC;
297168404Spjd
298168404Spjd	/* Make sure we're a network function */
299168404Spjd	error = pccard_get_function(dev, &fcn);
300168404Spjd	if (error != 0)
301185029Spjd		return (error);
302168404Spjd
303168404Spjd	if ((pp = (const struct ed_product *) pccard_product_lookup(dev,
304168404Spjd	    (const struct pccard_product *) ed_pccard_products,
305168404Spjd	    sizeof(ed_pccard_products[0]), NULL)) != NULL) {
306168404Spjd		if (pp->prod.pp_name != NULL)
307168404Spjd			device_set_desc(dev, pp->prod.pp_name);
308168404Spjd		/*
309168404Spjd		 * Some devices don't ID themselves as network, but
310168404Spjd		 * that's OK if the flags say so.
311168404Spjd		 */
312168404Spjd		if (!(pp->flags & NE2000DVF_ANYFUNC) &&
313168404Spjd		    fcn != PCCARD_FUNCTION_NETWORK)
314168404Spjd			return (ENXIO);
315168404Spjd		/*
316168404Spjd		 * Some devices match multiple entries.  Report that
317172443Spjd		 * as a warning to help cull the table
318172443Spjd		 */
319168404Spjd		pp2 = pp;
320168404Spjd		while ((pp2 = (const struct ed_product *)pccard_product_lookup(
321168404Spjd		    dev, (const struct pccard_product *)(pp2 + 1),
322168404Spjd		    sizeof(ed_pccard_products[0]), NULL)) != NULL) {
323168404Spjd			if (first) {
324168404Spjd				device_printf(dev,
325168404Spjd    "Warning: card matches multiple entries.  Report to imp@freebsd.org\n");
326168404Spjd				ed_pccard_print_entry(pp);
327185029Spjd				first = 0;
328168404Spjd			}
329168404Spjd			ed_pccard_print_entry(pp2);
330168404Spjd		}
331168404Spjd
332168404Spjd		return (0);
333168404Spjd	}
334168404Spjd	return (ENXIO);
335168404Spjd}
336185029Spjd
337185029Spjdstatic int
338185029Spjded_pccard_rom_mac(device_t dev, uint8_t *enaddr)
339185029Spjd{
340197150Spjd	struct ed_softc *sc = device_get_softc(dev);
341197150Spjd	uint8_t romdata[32], sum;
342197150Spjd	int i;
343197150Spjd
344197172Spjd	/*
345197150Spjd	 * Read in the rom data at location 0.  Since there are no
346197150Spjd	 * NE-1000 based PC Card devices, we'll assume we're 16-bit.
347185029Spjd	 *
348168404Spjd	 * In researching what format this takes, I've found that the
349168404Spjd	 * following appears to be true for multiple cards based on
350168404Spjd	 * observation as well as datasheet digging.
351168404Spjd	 *
352185029Spjd	 * Data is stored in some ROM and is copied out 8 bits at a time
353168404Spjd	 * into 16-bit wide locations.  This means that the odd locations
354168404Spjd	 * of the ROM are not used (and can be either 0 or ff).
355168404Spjd	 *
356168404Spjd	 * The contents appears to be as follows:
357168404Spjd	 * PROM   RAM
358168404Spjd	 * Offset Offset	What
359168404Spjd	 *  0      0	ENETADDR 0
360168404Spjd	 *  1      2	ENETADDR 1
361168404Spjd	 *  2      4	ENETADDR 2
362168404Spjd	 *  3      6	ENETADDR 3
363168404Spjd	 *  4      8	ENETADDR 4
364168404Spjd	 *  5     10	ENETADDR 5
365168404Spjd	 *  6-13  12-26 Reserved (varies by manufacturer)
366168404Spjd	 * 14     28	0x57
367168404Spjd	 * 15     30    0x57
368168404Spjd	 *
369168404Spjd	 * Some manufacturers have another image of enetaddr from
370168404Spjd	 * PROM offset 0x10 to 0x15 with 0x42 in 0x1e and 0x1f, but
371168404Spjd	 * this doesn't appear to be universally documented in the
372168404Spjd	 * datasheets.  Some manufactuers have a card type, card config
373168404Spjd	 * checksums, etc encoded into PROM offset 6-13, but deciphering it
374168404Spjd	 * requires more knowledge about the exact underlying chipset than
375168404Spjd	 * we possess (and maybe can possess).
376168404Spjd	 */
377168404Spjd	ed_pio_readmem(sc, 0, romdata, 32);
378168404Spjd	if (bootverbose)
379185029Spjd		device_printf(dev, "ROM DATA: %32D\n", romdata, " ");
380168404Spjd	if (romdata[28] != 0x57 || romdata[30] != 0x57)
381168404Spjd		return (0);
382168404Spjd	for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++)
383168404Spjd		sum |= romdata[i * 2];
384168404Spjd	if (sum == 0)
385168404Spjd		return (0);
386168404Spjd	for (i = 0; i < ETHER_ADDR_LEN; i++)
387168404Spjd		enaddr[i] = romdata[i * 2];
388168404Spjd	return (1);
389168404Spjd}
390168404Spjd
391168404Spjdstatic int
392168404Spjded_pccard_add_modem(device_t dev)
393168404Spjd{
394168404Spjd	device_printf(dev, "Need to write this code\n");
395168404Spjd	return 0;
396168404Spjd}
397168404Spjd
398168404Spjdstatic int
399168404Spjded_pccard_kick_phy(struct ed_softc *sc)
400168404Spjd{
401168404Spjd	struct mii_softc *miisc;
402168404Spjd	struct mii_data *mii;
403168404Spjd
404168404Spjd	/*
405168404Spjd	 * Many of the PHYs that wind up on PC Cards are weird in
406168404Spjd	 * this way.  Generally, we don't need to worry so much about
407168404Spjd	 * the Isolation protocol since there's only one PHY in
408168404Spjd	 * these designs, so this workaround is reasonable.
409168404Spjd	 */
410168404Spjd	mii = device_get_softc(sc->miibus);
411168404Spjd	LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
412168404Spjd		miisc->mii_flags |= MIIF_FORCEANEG;
413168404Spjd		mii_phy_reset(miisc);
414168404Spjd	}
415168404Spjd	return (mii_mediachg(mii));
416168404Spjd}
417168404Spjd
418168404Spjdstatic int
419168404Spjded_pccard_media_ioctl(struct ed_softc *sc, struct ifreq *ifr, u_long command)
420168404Spjd{
421168404Spjd	struct mii_data *mii;
422168404Spjd
423168404Spjd	if (sc->miibus == NULL)
424168404Spjd		return (EINVAL);
425168404Spjd	mii = device_get_softc(sc->miibus);
426168404Spjd	return (ifmedia_ioctl(sc->ifp, ifr, &mii->mii_media, command));
427168404Spjd}
428168404Spjd
429168404Spjd
430168404Spjdstatic void
431185029Spjded_pccard_mediachg(struct ed_softc *sc)
432168404Spjd{
433168404Spjd	struct mii_data *mii;
434168404Spjd
435168404Spjd	if (sc->miibus == NULL)
436168404Spjd		return;
437168404Spjd	mii = device_get_softc(sc->miibus);
438185029Spjd	mii_mediachg(mii);
439168404Spjd}
440168404Spjd
441168404Spjdstatic int
442168404Spjded_pccard_attach(device_t dev)
443168404Spjd{
444168404Spjd	u_char sum;
445168404Spjd	u_char enaddr[ETHER_ADDR_LEN];
446168404Spjd	const struct ed_product *pp;
447168404Spjd	int	error, i, flags, port_rid, modem_rid;
448168404Spjd	struct ed_softc *sc = device_get_softc(dev);
449168404Spjd	u_long size;
450168404Spjd	static uint16_t *intr_vals[] = {NULL, NULL};
451168404Spjd
452168404Spjd	sc->dev = dev;
453168404Spjd	if ((pp = (const struct ed_product *) pccard_product_lookup(dev,
454168404Spjd	    (const struct pccard_product *) ed_pccard_products,
455168404Spjd		 sizeof(ed_pccard_products[0]), NULL)) == NULL) {
456168404Spjd		printf("Can't find\n");
457185029Spjd		return (ENXIO);
458185029Spjd	}
459168404Spjd	modem_rid = port_rid = -1;
460168404Spjd	if (pp->flags & NE2000DVF_MODEM) {
461168404Spjd		for (i = 0; i < 4; i++) {
462185029Spjd			size = bus_get_resource_count(dev, SYS_RES_IOPORT, i);
463168404Spjd			if (size == ED_NOVELL_IO_PORTS)
464168404Spjd				port_rid = i;
465168404Spjd			else if (size == 8)
466168404Spjd				modem_rid = i;
467168404Spjd		}
468168404Spjd		if (port_rid == -1) {
469168404Spjd			device_printf(dev, "Cannot locate my ports!\n");
470168404Spjd			return (ENXIO);
471168404Spjd		}
472168404Spjd	} else {
473185029Spjd		port_rid = 0;
474185029Spjd	}
475185029Spjd	/* Allocate the port resource during setup. */
476185029Spjd	error = ed_alloc_port(dev, port_rid, ED_NOVELL_IO_PORTS);
477168404Spjd	if (error) {
478168404Spjd		printf("alloc_port failed\n");
479168404Spjd		return (error);
480185029Spjd	}
481168404Spjd	if (rman_get_size(sc->port_res) == ED_NOVELL_IO_PORTS / 2) {
482168404Spjd		port_rid++;
483168404Spjd		sc->port_res2 = bus_alloc_resource(dev, SYS_RES_IOPORT,
484168404Spjd		    &port_rid, 0ul, ~0ul, 1, RF_ACTIVE);
485168404Spjd		if (sc->port_res2 == NULL ||
486168404Spjd		    rman_get_size(sc->port_res2) != ED_NOVELL_IO_PORTS / 2) {
487168404Spjd			error = ENXIO;
488185029Spjd			goto bad;
489168404Spjd		}
490168404Spjd	}
491168404Spjd	error = ed_alloc_irq(dev, 0, 0);
492168404Spjd	if (error)
493185029Spjd		goto bad;
494185029Spjd
495185029Spjd	/*
496185029Spjd	 * Determine which chipset we are.  Almost all the PC Card chipsets
497185029Spjd	 * have the Novel ASIC and NIC offsets.  There's 2 known cards that
498185029Spjd	 * follow the WD80x3 conventions, which are handled as a special case.
499168404Spjd	 */
500168404Spjd	sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
501185029Spjd	sc->nic_offset  = ED_NOVELL_NIC_OFFSET;
502185029Spjd	error = ENXIO;
503168404Spjd	flags = device_get_flags(dev);
504168404Spjd	if (error != 0)
505168404Spjd		error = ed_pccard_dl100xx(dev, pp);
506185029Spjd	if (error != 0)
507168404Spjd		error = ed_pccard_ax88x90(dev, pp);
508168404Spjd	if (error != 0)
509168404Spjd		error = ed_pccard_tc5299j(dev, pp);
510168404Spjd	if (error != 0) {
511168404Spjd		error = ed_probe_Novell_generic(dev, flags);
512168404Spjd		printf("Novell probe generic %d\n", error);
513168404Spjd	}
514168404Spjd	if (error != 0 && (pp->flags & NE2000DVF_TOSHIBA)) {
515168404Spjd		flags |= ED_FLAGS_TOSH_ETHER;
516168404Spjd		flags |= ED_FLAGS_PCCARD;
517168404Spjd		sc->asic_offset = ED_WD_ASIC_OFFSET;
518168404Spjd		sc->nic_offset  = ED_WD_NIC_OFFSET;
519168404Spjd		error = ed_probe_WD80x3_generic(dev, flags, intr_vals);
520168404Spjd	}
521168404Spjd	if (error)
522168404Spjd		goto bad;
523168404Spjd
524168404Spjd	/*
525185029Spjd	 * There are several ways to get the MAC address for the card.
526168404Spjd	 * Some of the above probe routines can fill in the enaddr.  If
527168404Spjd	 * not, we run through a number of 'well known' locations:
528168404Spjd	 *	(1) From the PC Card FUNCE
529168404Spjd	 *	(2) From offset 0 in the shared memory
530168404Spjd	 *	(3) From a hinted offset in attribute memory
531168404Spjd	 *	(4) From 0xff0 in attribute memory
532168404Spjd	 * If we can't get a non-zero MAC address from this list, we fail.
533185029Spjd	 */
534185029Spjd	for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++)
535185029Spjd		sum |= sc->enaddr[i];
536185029Spjd	if (sum == 0) {
537185029Spjd		pccard_get_ether(dev, enaddr);
538185029Spjd		if (bootverbose)
539185029Spjd			device_printf(dev, "CIS MAC %6D\n", enaddr, ":");
540185029Spjd		for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++)
541185029Spjd			sum |= enaddr[i];
542168404Spjd		if (sum == 0 && ed_pccard_rom_mac(dev, enaddr)) {
543168404Spjd			if (bootverbose)
544168404Spjd				device_printf(dev, "ROM mac %6D\n", enaddr,
545168404Spjd				    ":");
546168404Spjd			sum++;
547185029Spjd		}
548168404Spjd		if (sum == 0 && pp->flags & NE2000DVF_ENADDR) {
549168404Spjd			for (i = 0; i < ETHER_ADDR_LEN; i++) {
550168404Spjd				pccard_attr_read_1(dev, pp->enoff + i * 2,
551168404Spjd				    enaddr + i);
552168404Spjd				sum |= enaddr[i];
553168404Spjd			}
554168404Spjd			if (bootverbose)
555185029Spjd				device_printf(dev, "Hint %x MAC %6D\n",
556185029Spjd				    pp->enoff, enaddr, ":");
557185029Spjd		}
558185029Spjd		if (sum == 0) {
559185029Spjd			for (i = 0; i < ETHER_ADDR_LEN; i++) {
560185029Spjd				pccard_attr_read_1(dev, ED_DEFAULT_MAC_OFFSET +
561185029Spjd				    i * 2, enaddr + i);
562168404Spjd				sum |= enaddr[i];
563168404Spjd			}
564185029Spjd			if (bootverbose)
565168404Spjd				device_printf(dev, "Fallback MAC %6D\n",
566168404Spjd				    enaddr, ":");
567168404Spjd		}
568168404Spjd		if (sum == 0) {
569168404Spjd			device_printf(dev, "Cannot extract MAC address.\n");
570168404Spjd			ed_release_resources(dev);
571168404Spjd			return (ENXIO);
572168404Spjd		}
573168404Spjd		bcopy(enaddr, sc->enaddr, ETHER_ADDR_LEN);
574168404Spjd	}
575168404Spjd
576168404Spjd	error = ed_attach(dev);
577168404Spjd	if (error)
578168404Spjd		goto bad;
579168404Spjd 	if (sc->chip_type == ED_CHIP_TYPE_DL10019 ||
580168404Spjd	    sc->chip_type == ED_CHIP_TYPE_DL10022) {
581168404Spjd		/* Probe for an MII bus, but ignore errors. */
582168404Spjd		ed_pccard_dl100xx_mii_reset(sc);
583168404Spjd		(void)mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd,
584168404Spjd		    ed_ifmedia_sts);
585168404Spjd	} else if (sc->chip_type == ED_CHIP_TYPE_AX88190 ||
586168404Spjd	    sc->chip_type == ED_CHIP_TYPE_AX88790) {
587168404Spjd		if ((error = mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd,
588168404Spjd		     ed_ifmedia_sts)) != 0) {
589168404Spjd			device_printf(dev, "Missing mii %d!\n", error);
590168404Spjd			goto bad;
591168404Spjd		}
592168404Spjd
593168404Spjd	} else if (sc->chip_type == ED_CHIP_TYPE_TC5299J) {
594168404Spjd		if ((error = mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd,
595168404Spjd		     ed_ifmedia_sts)) != 0) {
596168404Spjd			device_printf(dev, "Missing mii!\n");
597168404Spjd			goto bad;
598168404Spjd		}
599168404Spjd
600168404Spjd	}
601168404Spjd	if (sc->miibus != NULL) {
602185029Spjd		sc->sc_tick = ed_pccard_tick;
603168404Spjd		sc->sc_mediachg = ed_pccard_mediachg;
604168404Spjd		sc->sc_media_ioctl = ed_pccard_media_ioctl;
605168404Spjd		ed_pccard_kick_phy(sc);
606168404Spjd	} else {
607168404Spjd		ed_gen_ifmedia_init(sc);
608168404Spjd	}
609168404Spjd	if (modem_rid != -1)
610168404Spjd		ed_pccard_add_modem(dev);
611168404Spjd
612168404Spjd	error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
613168404Spjd	    NULL, edintr, sc, &sc->irq_handle);
614168404Spjd	if (error) {
615185029Spjd		device_printf(dev, "setup intr failed %d \n", error);
616185029Spjd		goto bad;
617168404Spjd	}
618185029Spjd
619185029Spjd	return (0);
620185029Spjdbad:
621185029Spjd	ed_detach(dev);
622185029Spjd	return (error);
623185029Spjd}
624168404Spjd
625185029Spjd/*
626185029Spjd * Probe the Ethernet MAC addrees for PCMCIA Linksys EtherFast 10/100
627185029Spjd * and compatible cards (DL10019C Ethernet controller).
628185029Spjd */
629185029Spjdstatic int
630185029Spjded_pccard_dl100xx(device_t dev, const struct ed_product *pp)
631185029Spjd{
632185029Spjd	struct ed_softc *sc = device_get_softc(dev);
633185029Spjd	u_char sum;
634185029Spjd	uint8_t id;
635185029Spjd	u_int   memsize;
636185029Spjd	int i, error;
637185029Spjd
638185029Spjd	if (!(pp->flags & NE2000DVF_DL100XX))
639185029Spjd		return (ENXIO);
640185029Spjd	if (bootverbose)
641185029Spjd		device_printf(dev, "Trying DL100xx probing\n");
642185029Spjd	error = ed_probe_Novell_generic(dev, device_get_flags(dev));
643185029Spjd	if (bootverbose && error)
644185029Spjd		device_printf(dev, "Novell generic probe failed: %d\n", error);
645185029Spjd	if (error != 0)
646185029Spjd		return (error);
647185029Spjd
648185029Spjd	/*
649185029Spjd	 * Linksys registers(offset from ASIC base)
650185029Spjd	 *
651185029Spjd	 * 0x04-0x09 : Physical Address Register 0-5 (PAR0-PAR5)
652185029Spjd	 * 0x0A      : Card ID Register (CIR)
653185029Spjd	 * 0x0B      : Check Sum Register (SR)
654185029Spjd	 */
655185029Spjd	for (sum = 0, i = 0x04; i < 0x0c; i++)
656185029Spjd		sum += ed_asic_inb(sc, i);
657185029Spjd	if (sum != 0xff) {
658185029Spjd		if (bootverbose)
659168404Spjd			device_printf(dev, "Bad checksum %#x\n", sum);
660168404Spjd		return (ENXIO);		/* invalid DL10019C */
661168404Spjd	}
662168404Spjd	if (bootverbose)
663185029Spjd		device_printf(dev, "CIR is %d\n", ed_asic_inb(sc, 0xa));
664185029Spjd	for (i = 0; i < ETHER_ADDR_LEN; i++)
665185029Spjd		sc->enaddr[i] = ed_asic_inb(sc, 0x04 + i);
666185029Spjd	ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
667185029Spjd	id = ed_asic_inb(sc, 0xf);
668185029Spjd	sc->isa16bit = 1;
669185029Spjd	/*
670185029Spjd	 * Hard code values based on the datasheet.  We're NE-2000 compatible
671185029Spjd	 * NIC with 24kb of packet memory starting at 24k offset.  These
672185029Spjd	 * cards also work with 16k at 16k, but don't work with 24k at 16k
673168404Spjd	 * or 32k at 16k.
674168404Spjd	 */
675168404Spjd	sc->type = ED_TYPE_NE2000;
676185029Spjd	sc->mem_start = 24 * 1024;
677168404Spjd	memsize = sc->mem_size = 24 * 1024;
678185029Spjd	sc->mem_end = sc->mem_start + memsize;
679168404Spjd	sc->tx_page_start = memsize / ED_PAGE_SIZE;
680168404Spjd	sc->txb_cnt = 3;
681185029Spjd	sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
682185029Spjd	sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE;
683185029Spjd
684185029Spjd	sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
685185029Spjd
686185029Spjd	ed_nic_outb(sc, ED_P0_PSTART, sc->mem_start / ED_PAGE_SIZE);
687168404Spjd	ed_nic_outb(sc, ED_P0_PSTOP, sc->mem_end / ED_PAGE_SIZE);
688185029Spjd	sc->vendor = ED_VENDOR_NOVELL;
689185029Spjd	sc->chip_type = (id & 0x90) == 0x90 ?
690168404Spjd	    ED_CHIP_TYPE_DL10022 : ED_CHIP_TYPE_DL10019;
691185029Spjd	sc->type_str = ((id & 0x90) == 0x90) ? "DL10022" : "DL10019";
692168404Spjd	sc->mii_readbits = ed_pccard_dl100xx_mii_readbits;
693168404Spjd	sc->mii_writebits = ed_pccard_dl100xx_mii_writebits;
694168404Spjd	return (0);
695185029Spjd}
696168404Spjd
697185029Spjd/* MII bit-twiddling routines for cards using Dlink chipset */
698168404Spjd#define DL100XX_MIISET(sc, x) ed_asic_outb(sc, ED_DL100XX_MIIBUS, \
699185029Spjd    ed_asic_inb(sc, ED_DL100XX_MIIBUS) | (x))
700168404Spjd#define DL100XX_MIICLR(sc, x) ed_asic_outb(sc, ED_DL100XX_MIIBUS, \
701185029Spjd    ed_asic_inb(sc, ED_DL100XX_MIIBUS) & ~(x))
702185029Spjd
703185029Spjdstatic void
704185029Spjded_pccard_dl100xx_mii_reset(struct ed_softc *sc)
705185029Spjd{
706185029Spjd	if (sc->chip_type != ED_CHIP_TYPE_DL10022)
707185029Spjd		return;
708168404Spjd
709168404Spjd	ed_asic_outb(sc, ED_DL100XX_MIIBUS, ED_DL10022_MII_RESET2);
710185029Spjd	DELAY(10);
711168404Spjd	ed_asic_outb(sc, ED_DL100XX_MIIBUS,
712168404Spjd	    ED_DL10022_MII_RESET2 | ED_DL10022_MII_RESET1);
713168404Spjd	DELAY(10);
714168404Spjd	ed_asic_outb(sc, ED_DL100XX_MIIBUS, ED_DL10022_MII_RESET2);
715168404Spjd	DELAY(10);
716168404Spjd	ed_asic_outb(sc, ED_DL100XX_MIIBUS,
717168404Spjd	    ED_DL10022_MII_RESET2 | ED_DL10022_MII_RESET1);
718168404Spjd	DELAY(10);
719168404Spjd	ed_asic_outb(sc, ED_DL100XX_MIIBUS, 0);
720168404Spjd}
721168404Spjd
722185029Spjdstatic void
723168404Spjded_pccard_dl100xx_mii_writebits(struct ed_softc *sc, u_int val, int nbits)
724185029Spjd{
725168404Spjd	int i;
726168404Spjd
727185029Spjd	DL100XX_MIISET(sc, ED_DL100XX_MII_DIROUT);
728185029Spjd	for (i = nbits - 1; i >= 0; i--) {
729185029Spjd		if ((val >> i) & 1)
730185029Spjd			DL100XX_MIISET(sc, ED_DL100XX_MII_DATAOUT);
731185029Spjd		else
732168404Spjd			DL100XX_MIICLR(sc, ED_DL100XX_MII_DATAOUT);
733185029Spjd		DL100XX_MIISET(sc, ED_DL100XX_MII_CLK);
734168404Spjd		DL100XX_MIICLR(sc, ED_DL100XX_MII_CLK);
735185029Spjd	}
736168404Spjd}
737168404Spjd
738168404Spjdstatic u_int
739168404Spjded_pccard_dl100xx_mii_readbits(struct ed_softc *sc, int nbits)
740168404Spjd{
741168404Spjd	int i;
742168404Spjd	u_int val = 0;
743168404Spjd
744168404Spjd	DL100XX_MIICLR(sc, ED_DL100XX_MII_DIROUT);
745185029Spjd	for (i = nbits - 1; i >= 0; i--) {
746168404Spjd		DL100XX_MIISET(sc, ED_DL100XX_MII_CLK);
747168404Spjd		val <<= 1;
748168404Spjd		if (ed_asic_inb(sc, ED_DL100XX_MIIBUS) & ED_DL100XX_MII_DATAIN)
749168404Spjd			val++;
750168404Spjd		DL100XX_MIICLR(sc, ED_DL100XX_MII_CLK);
751185029Spjd	}
752168404Spjd	return val;
753168404Spjd}
754185029Spjd
755168404Spjdstatic void
756168404Spjded_pccard_ax88x90_reset(struct ed_softc *sc)
757168404Spjd{
758185029Spjd	int i;
759185029Spjd
760168404Spjd	/* Reset Card */
761168404Spjd	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP | ED_CR_PAGE_0);
762168404Spjd	ed_asic_outb(sc, ED_NOVELL_RESET, ed_asic_inb(sc, ED_NOVELL_RESET));
763168404Spjd
764168404Spjd	/* Wait for the RST bit to assert, but cap it at 10ms */
765185029Spjd	for (i = 10000; !(ed_nic_inb(sc, ED_P0_ISR) & ED_ISR_RST) && i > 0;
766168404Spjd	     i--)
767168404Spjd		continue;
768168404Spjd	ed_nic_outb(sc, ED_P0_ISR, ED_ISR_RST);	/* ACK INTR */
769185029Spjd	if (i == 0)
770168404Spjd		device_printf(sc->dev, "Reset didn't finish\n");
771168404Spjd}
772168404Spjd
773168404Spjd/*
774168404Spjd * Probe and vendor-specific initialization routine for ax88x90 boards
775168404Spjd */
776168404Spjdstatic int
777168404Spjded_probe_ax88x90_generic(device_t dev, int flags)
778168404Spjd{
779185029Spjd	struct ed_softc *sc = device_get_softc(dev);
780168404Spjd	u_int   memsize;
781168404Spjd	static char test_pattern[32] = "THIS is A memory TEST pattern";
782168404Spjd	char    test_buffer[32];
783168404Spjd
784168404Spjd	ed_pccard_ax88x90_reset(sc);
785197150Spjd	DELAY(10*1000);
786168404Spjd
787168404Spjd	/* Make sure that we really have an 8390 based board */
788168404Spjd	if (!ed_probe_generic8390(sc))
789168404Spjd		return (ENXIO);
790168404Spjd
791168404Spjd	sc->vendor = ED_VENDOR_NOVELL;
792168404Spjd	sc->mem_shared = 0;
793168404Spjd	sc->cr_proto = ED_CR_RD2;
794168404Spjd
795168404Spjd	/*
796168404Spjd	 * This prevents packets from being stored in the NIC memory when the
797168404Spjd	 * readmem routine turns on the start bit in the CR.  We write some
798168404Spjd	 * bytes in word mode and verify we can read them back.  If we can't
799168404Spjd	 * then we don't have an AX88x90 chip here.
800168404Spjd	 */
801168404Spjd	sc->isa16bit = 1;
802168404Spjd	ed_nic_outb(sc, ED_P0_RCR, ED_RCR_MON);
803168404Spjd	ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
804168404Spjd	ed_pio_writemem(sc, test_pattern, 16384, sizeof(test_pattern));
805185029Spjd	ed_pio_readmem(sc, 16384, test_buffer, sizeof(test_pattern));
806168404Spjd	if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) != 0)
807185029Spjd		return (ENXIO);
808168404Spjd
809168404Spjd	/*
810185029Spjd	 * Hard code values based on the datasheet.  We're NE-2000 compatible
811185029Spjd	 * NIC with 16kb of packet memory starting at 16k offset.
812185029Spjd	 */
813185029Spjd	sc->type = ED_TYPE_NE2000;
814185029Spjd	memsize = sc->mem_size = 16*1024;
815168404Spjd	sc->mem_start = 16 * 1024;
816185029Spjd	if (ed_asic_inb(sc, ED_AX88X90_TEST) != 0)
817185029Spjd		sc->chip_type = ED_CHIP_TYPE_AX88790;
818168404Spjd	else {
819168404Spjd		sc->chip_type = ED_CHIP_TYPE_AX88190;
820168404Spjd		/*
821168404Spjd		 * The AX88190 (not A) has external 64k SRAM.  Probe for this
822185029Spjd		 * here.  Most of the cards I have either use the AX88190A
823185029Spjd		 * part, or have only 32k SRAM for some reason, so I don't
824185029Spjd		 * know if this works or not.
825185029Spjd		 */
826168404Spjd		ed_pio_writemem(sc, test_pattern, 32768, sizeof(test_pattern));
827185029Spjd		ed_pio_readmem(sc, 32768, test_buffer, sizeof(test_pattern));
828168404Spjd		if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) {
829168404Spjd			sc->mem_start = 2*1024;
830168404Spjd			memsize = sc->mem_size = 62 * 1024;
831185029Spjd		}
832168404Spjd	}
833168404Spjd	sc->mem_end = sc->mem_start + memsize;
834185029Spjd	sc->tx_page_start = memsize / ED_PAGE_SIZE;
835185029Spjd	if (sc->mem_size > 16 * 1024)
836185029Spjd		sc->txb_cnt = 3;
837185029Spjd	else
838168404Spjd		sc->txb_cnt = 2;
839168404Spjd	sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
840168404Spjd	sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE;
841168404Spjd
842168404Spjd	sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
843168404Spjd
844168404Spjd	ed_nic_outb(sc, ED_P0_PSTART, sc->mem_start / ED_PAGE_SIZE);
845168404Spjd	ed_nic_outb(sc, ED_P0_PSTOP, sc->mem_end / ED_PAGE_SIZE);
846168404Spjd
847168404Spjd	/* Get the mac before we go -- It's just at 0x400 in "SRAM" */
848185029Spjd	ed_pio_readmem(sc, 0x400, sc->enaddr, ETHER_ADDR_LEN);
849168404Spjd
850168404Spjd	/* clear any pending interrupts that might have occurred above */
851185029Spjd	ed_nic_outb(sc, ED_P0_ISR, 0xff);
852168404Spjd	sc->sc_write_mbufs = ed_pio_write_mbufs;
853168404Spjd	return (0);
854185029Spjd}
855185029Spjd
856185029Spjdstatic int
857185029Spjded_pccard_ax88x90_check_mii(device_t dev, struct ed_softc *sc)
858185029Spjd{
859168404Spjd	int	i, id;
860185029Spjd
861185029Spjd	/*
862168404Spjd	 * All AX88x90 devices have MII and a PHY, so we use this to weed out
863168404Spjd	 * chips that would otherwise make it through the tests we have after
864168404Spjd	 * this point.
865168404Spjd	 */
866185029Spjd	for (i = 0; i < 32; i++) {
867185029Spjd		id = ed_miibus_readreg(dev, i, MII_BMSR);
868185029Spjd		if (id != 0 && id != 0xffff)
869185029Spjd			break;
870185029Spjd	}
871168404Spjd	/*
872185029Spjd	 * Found one, we're good.
873168404Spjd	 */
874168404Spjd	if (i != 32)
875168404Spjd		return (0);
876168404Spjd	/*
877168404Spjd	 * Didn't find anything, so try to power up and try again.  The PHY
878185029Spjd	 * may be not responding because we're in power down mode.
879168404Spjd	 */
880168404Spjd	if (sc->chip_type == ED_CHIP_TYPE_AX88190)
881185029Spjd		return (ENXIO);
882185029Spjd	pccard_ccr_write_1(dev, PCCARD_CCR_STATUS, PCCARD_CCR_STATUS_PWRDWN);
883185029Spjd	for (i = 0; i < 32; i++) {
884185029Spjd		id = ed_miibus_readreg(dev, i, MII_BMSR);
885168404Spjd		if (id != 0 && id != 0xffff)
886168404Spjd			break;
887168404Spjd	}
888168404Spjd	/*
889168404Spjd	 * Still no joy?  We're AFU, punt.
890168404Spjd	 */
891185029Spjd	if (i == 32)
892185029Spjd		return (ENXIO);
893185029Spjd	return (0);
894185029Spjd
895185029Spjd}
896185029Spjd
897185029Spjd/*
898168404Spjd * Special setup for AX88[17]90
899168404Spjd */
900168404Spjdstatic int
901185029Spjded_pccard_ax88x90(device_t dev, const struct ed_product *pp)
902168404Spjd{
903185029Spjd	int	error;
904168404Spjd	int iobase;
905168404Spjd	struct	ed_softc *sc = device_get_softc(dev);
906185029Spjd
907185029Spjd	if (!(pp->flags & NE2000DVF_AX88X90))
908185029Spjd		return (ENXIO);
909185029Spjd
910185029Spjd	if (bootverbose)
911168404Spjd		device_printf(dev, "Checking AX88x90\n");
912185029Spjd
913168404Spjd	/*
914185029Spjd	 * Set the IOBASE Register.  The AX88x90 cards are potentially
915168404Spjd	 * multifunction cards, and thus requires a slight workaround.
916168404Spjd	 * We write the address the card is at, on the off chance that this
917168404Spjd	 * card is not MFC.
918168404Spjd	 * XXX I'm not sure that this is still needed...
919168404Spjd	 */
920168404Spjd	iobase = rman_get_start(sc->port_res);
921168404Spjd	pccard_ccr_write_1(dev, PCCARD_CCR_IOBASE0, iobase & 0xff);
922168404Spjd	pccard_ccr_write_1(dev, PCCARD_CCR_IOBASE1, (iobase >> 8) & 0xff);
923168404Spjd
924185029Spjd	sc->mii_readbits = ed_pccard_ax88x90_mii_readbits;
925168404Spjd	sc->mii_writebits = ed_pccard_ax88x90_mii_writebits;
926168404Spjd	error = ed_probe_ax88x90_generic(dev, device_get_flags(dev));
927168404Spjd	if (error) {
928168404Spjd		if (bootverbose)
929168404Spjd			device_printf(dev, "probe ax88x90 failed %d\n",
930168404Spjd			    error);
931168404Spjd		goto fail;
932168404Spjd	}
933168404Spjd	error = ed_pccard_ax88x90_check_mii(dev, sc);
934168404Spjd	if (error)
935168404Spjd		goto fail;
936168404Spjd	sc->vendor = ED_VENDOR_NOVELL;
937168404Spjd	sc->type = ED_TYPE_NE2000;
938168404Spjd	if (sc->chip_type == ED_CHIP_TYPE_AX88190)
939168404Spjd		sc->type_str = "AX88190";
940168404Spjd	else
941168404Spjd		sc->type_str = "AX88790";
942168404Spjd	return (0);
943168404Spjdfail:;
944168404Spjd	sc->mii_readbits = 0;
945168404Spjd	sc->mii_writebits = 0;
946168404Spjd	return (error);
947168404Spjd}
948168404Spjd
949168404Spjdstatic void
950168404Spjded_pccard_ax88x90_mii_writebits(struct ed_softc *sc, u_int val, int nbits)
951168404Spjd{
952168404Spjd	int i, data;
953168404Spjd
954168404Spjd	for (i = nbits - 1; i >= 0; i--) {
955168404Spjd		data = (val >> i) & 1 ? ED_AX88X90_MII_DATAOUT : 0;
956168404Spjd		ed_asic_outb(sc, ED_AX88X90_MIIBUS, data);
957168404Spjd		ed_asic_outb(sc, ED_AX88X90_MIIBUS, data | ED_AX88X90_MII_CLK);
958168404Spjd	}
959168404Spjd}
960168404Spjd
961168404Spjdstatic u_int
962168404Spjded_pccard_ax88x90_mii_readbits(struct ed_softc *sc, int nbits)
963168404Spjd{
964168404Spjd	int i;
965168404Spjd	u_int val = 0;
966168404Spjd	uint8_t mdio;
967168404Spjd
968168404Spjd	mdio = ED_AX88X90_MII_DIRIN;
969168404Spjd	for (i = nbits - 1; i >= 0; i--) {
970168404Spjd		ed_asic_outb(sc, ED_AX88X90_MIIBUS, mdio);
971168404Spjd		val <<= 1;
972168404Spjd		if (ed_asic_inb(sc, ED_AX88X90_MIIBUS) & ED_AX88X90_MII_DATAIN)
973168404Spjd			val++;
974168404Spjd		ed_asic_outb(sc, ED_AX88X90_MIIBUS, mdio | ED_AX88X90_MII_CLK);
975168404Spjd	}
976168404Spjd	return val;
977168404Spjd}
978168404Spjd
979168404Spjd/*
980168404Spjd * Special setup for TC5299J
981168404Spjd */
982168404Spjdstatic int
983168404Spjded_pccard_tc5299j(device_t dev, const struct ed_product *pp)
984168404Spjd{
985168404Spjd	int	error, i, id;
986168404Spjd	char *ts;
987168404Spjd	struct	ed_softc *sc = device_get_softc(dev);
988168404Spjd
989168404Spjd	if (!(pp->flags & NE2000DVF_TC5299J))
990168404Spjd		return (ENXIO);
991168404Spjd
992168404Spjd	if (bootverbose)
993168404Spjd		device_printf(dev, "Checking Tc5299j\n");
994168404Spjd
995168404Spjd	error = ed_probe_Novell_generic(dev, device_get_flags(dev));
996168404Spjd	if (bootverbose)
997168404Spjd		device_printf(dev, "probe novel returns %d\n", error);
998168404Spjd	if (error != 0)
999168404Spjd		return (error);
1000168404Spjd
1001168404Spjd	/*
1002168404Spjd	 * Check to see if we have a MII PHY ID at any address.  All TC5299J
1003168404Spjd	 * devices have MII and a PHY, so we use this to weed out chips that
1004168404Spjd	 * would otherwise make it through the tests we have after this point.
1005185029Spjd	 */
1006168404Spjd	sc->mii_readbits = ed_pccard_tc5299j_mii_readbits;
1007168404Spjd	sc->mii_writebits = ed_pccard_tc5299j_mii_writebits;
1008168404Spjd	for (i = 0; i < 32; i++) {
1009168404Spjd		id = ed_miibus_readreg(dev, i, MII_PHYIDR1);
1010168404Spjd		if (id != 0 && id != 0xffff)
1011168404Spjd			break;
1012168404Spjd	}
1013168404Spjd	if (i == 32) {
1014168404Spjd		sc->mii_readbits = 0;
1015168404Spjd		sc->mii_writebits = 0;
1016168404Spjd		return (ENXIO);
1017168404Spjd	}
1018168404Spjd	ts = "TC5299J";
1019168404Spjd	if (ed_pccard_rom_mac(dev, sc->enaddr) == 0) {
1020168404Spjd		sc->mii_readbits = 0;
1021168404Spjd		sc->mii_writebits = 0;
1022168404Spjd		return (ENXIO);
1023168404Spjd	}
1024168404Spjd	sc->vendor = ED_VENDOR_NOVELL;
1025185029Spjd	sc->type = ED_TYPE_NE2000;
1026185029Spjd	sc->chip_type = ED_CHIP_TYPE_TC5299J;
1027185029Spjd	sc->type_str = ts;
1028185029Spjd	return (0);
1029185029Spjd}
1030185029Spjd
1031168404Spjdstatic void
1032168404Spjded_pccard_tc5299j_mii_writebits(struct ed_softc *sc, u_int val, int nbits)
1033168404Spjd{
1034168404Spjd	int i;
1035168404Spjd	uint8_t cr, data;
1036168404Spjd
1037168404Spjd	/* Select page 3 */
1038168404Spjd	cr = ed_nic_inb(sc, ED_P0_CR);
1039168404Spjd	ed_nic_outb(sc, ED_P0_CR, cr | ED_CR_PAGE_3);
1040168404Spjd
1041168404Spjd	for (i = nbits - 1; i >= 0; i--) {
1042168404Spjd		data = (val >> i) & 1 ? ED_TC5299J_MII_DATAOUT : 0;
1043168404Spjd		ed_nic_outb(sc, ED_TC5299J_MIIBUS, data);
1044168404Spjd		ed_nic_outb(sc, ED_TC5299J_MIIBUS, data | ED_TC5299J_MII_CLK);
1045168404Spjd	}
1046168404Spjd	ed_nic_outb(sc, ED_TC5299J_MIIBUS, 0);
1047168404Spjd
1048168404Spjd	/* Restore prior page */
1049168404Spjd	ed_nic_outb(sc, ED_P0_CR, cr);
1050168404Spjd}
1051168404Spjd
1052168404Spjdstatic u_int
1053168404Spjded_pccard_tc5299j_mii_readbits(struct ed_softc *sc, int nbits)
1054168404Spjd{
1055168404Spjd	int i;
1056168404Spjd	u_int val = 0;
1057168404Spjd	uint8_t cr;
1058168404Spjd
1059168404Spjd	/* Select page 3 */
1060168404Spjd	cr = ed_nic_inb(sc, ED_P0_CR);
1061168404Spjd	ed_nic_outb(sc, ED_P0_CR, cr | ED_CR_PAGE_3);
1062168404Spjd
1063168404Spjd	ed_asic_outb(sc, ED_TC5299J_MIIBUS, ED_TC5299J_MII_DIROUT);
1064168404Spjd	for (i = nbits - 1; i >= 0; i--) {
1065168404Spjd		ed_nic_outb(sc, ED_TC5299J_MIIBUS,
1066185029Spjd		    ED_TC5299J_MII_CLK | ED_TC5299J_MII_DIROUT);
1067168404Spjd		val <<= 1;
1068168404Spjd		if (ed_nic_inb(sc, ED_TC5299J_MIIBUS) & ED_TC5299J_MII_DATAIN)
1069168404Spjd			val++;
1070168404Spjd		ed_nic_outb(sc, ED_TC5299J_MIIBUS, ED_TC5299J_MII_DIROUT);
1071168404Spjd	}
1072168404Spjd
1073168404Spjd	/* Restore prior page */
1074168404Spjd	ed_nic_outb(sc, ED_P0_CR, cr);
1075168404Spjd	return val;
1076168404Spjd}
1077168404Spjd
1078168404Spjd/*
1079168404Spjd * MII bus support routines.
1080168404Spjd */
1081168404Spjdstatic int
1082209962Smmed_miibus_readreg(device_t dev, int phy, int reg)
1083209962Smm{
1084209962Smm	struct ed_softc *sc;
1085209962Smm	int failed, val;
1086209962Smm
1087209962Smm	sc = device_get_softc(dev);
1088209962Smm	/*
1089209962Smm	 * The AX88790 has an interesting quirk.  It has an internal phy that
1090209962Smm	 * needs a special bit set to access, but can also have additional
1091209962Smm	 * external PHYs set for things like HomeNET media.  When accessing
1092209962Smm	 * the internal PHY, a bit has to be set, when accessing the external
1093209962Smm	 * PHYs, it must be clear.  See Errata 1, page 51, in the AX88790
1094209962Smm	 * datasheet for more details.
1095209962Smm	 *
1096209962Smm	 * Also, PHYs above 16 appear to be phantoms on some cards, but not
1097209962Smm	 * others.  Registers read for this are often the same as prior values
1098209962Smm	 * read.  Filter all register requests to 17-31.
1099209962Smm	 *
1100209962Smm	 * I can't explain it, since I don't have the DL100xx data sheets, but
1101209962Smm	 * the DL100xx chips do 13-bits before the 'ACK' but, but the AX88x90
1102209962Smm	 * chips have 14.  The linux pcnet and axnet drivers confirm this.
1103209962Smm	 */
1104209962Smm	if (sc->chip_type == ED_CHIP_TYPE_AX88790) {
1105209962Smm		if (phy > 0x10)
1106209962Smm			return (0);
1107209962Smm		if (phy == 0x10)
1108209962Smm			ed_asic_outb(sc, ED_AX88X90_GPIO,
1109209962Smm			    ED_AX88X90_GPIO_INT_PHY);
1110209962Smm		else
1111209962Smm			ed_asic_outb(sc, ED_AX88X90_GPIO, 0);
1112209962Smm	}
1113209962Smm
1114209962Smm	(*sc->mii_writebits)(sc, 0xffffffff, 32);
1115209962Smm	(*sc->mii_writebits)(sc, ED_MII_STARTDELIM, ED_MII_STARTDELIM_BITS);
1116209962Smm	(*sc->mii_writebits)(sc, ED_MII_READOP, ED_MII_OP_BITS);
1117209962Smm	(*sc->mii_writebits)(sc, phy, ED_MII_PHY_BITS);
1118209962Smm	(*sc->mii_writebits)(sc, reg, ED_MII_REG_BITS);
1119209962Smm	if (sc->chip_type == ED_CHIP_TYPE_AX88790 ||
1120209962Smm	    sc->chip_type == ED_CHIP_TYPE_AX88190)
1121209962Smm		(*sc->mii_readbits)(sc, ED_MII_ACK_BITS);
1122209962Smm	failed = (*sc->mii_readbits)(sc, ED_MII_ACK_BITS);
1123209962Smm	val = (*sc->mii_readbits)(sc, ED_MII_DATA_BITS);
1124209962Smm	(*sc->mii_writebits)(sc, ED_MII_IDLE, ED_MII_IDLE_BITS);
1125209962Smm/*	printf("Reading phy %d reg %#x returning %#x (valid %d)\n", phy, reg, val, !failed); */
1126209962Smm	return (failed ? 0 : val);
1127209962Smm}
1128209962Smm
1129209962Smmstatic int
1130209962Smmed_miibus_writereg(device_t dev, int phy, int reg, int data)
1131209962Smm{
1132209962Smm	struct ed_softc *sc;
1133209962Smm
1134209962Smm/*	printf("Writing phy %d reg %#x data %#x\n", phy, reg, data); */
1135209962Smm	sc = device_get_softc(dev);
1136209962Smm	/* See ed_miibus_readreg for details */
1137209962Smm	if (sc->chip_type == ED_CHIP_TYPE_AX88790) {
1138209962Smm		if (phy > 0x10)
1139209962Smm			return (0);
1140209962Smm		if (phy == 0x10)
1141209962Smm			ed_asic_outb(sc, ED_AX88X90_GPIO,
1142209962Smm			    ED_AX88X90_GPIO_INT_PHY);
1143209962Smm		else
1144209962Smm			ed_asic_outb(sc, ED_AX88X90_GPIO, 0);
1145209962Smm	}
1146209962Smm	(*sc->mii_writebits)(sc, 0xffffffff, 32);
1147209962Smm	(*sc->mii_writebits)(sc, ED_MII_STARTDELIM, ED_MII_STARTDELIM_BITS);
1148209962Smm	(*sc->mii_writebits)(sc, ED_MII_WRITEOP, ED_MII_OP_BITS);
1149209962Smm	(*sc->mii_writebits)(sc, phy, ED_MII_PHY_BITS);
1150209962Smm	(*sc->mii_writebits)(sc, reg, ED_MII_REG_BITS);
1151209962Smm	(*sc->mii_writebits)(sc, ED_MII_TURNAROUND, ED_MII_TURNAROUND_BITS);
1152209962Smm	(*sc->mii_writebits)(sc, data, ED_MII_DATA_BITS);
1153209962Smm	(*sc->mii_writebits)(sc, ED_MII_IDLE, ED_MII_IDLE_BITS);
1154209962Smm	return (0);
1155209962Smm}
1156209962Smm
1157209962Smmstatic int
1158ed_ifmedia_upd(struct ifnet *ifp)
1159{
1160	struct ed_softc *sc;
1161	int error;
1162
1163	sc = ifp->if_softc;
1164	if (sc->miibus == NULL)
1165		return (ENXIO);
1166	ED_LOCK(sc);
1167	error = ed_pccard_kick_phy(sc);
1168	ED_UNLOCK(sc);
1169	return (error);
1170}
1171
1172static void
1173ed_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
1174{
1175	struct ed_softc *sc;
1176	struct mii_data *mii;
1177
1178	sc = ifp->if_softc;
1179	if (sc->miibus == NULL)
1180		return;
1181
1182	mii = device_get_softc(sc->miibus);
1183	mii_pollstat(mii);
1184	ifmr->ifm_active = mii->mii_media_active;
1185	ifmr->ifm_status = mii->mii_media_status;
1186}
1187
1188static void
1189ed_child_detached(device_t dev, device_t child)
1190{
1191	struct ed_softc *sc;
1192
1193	sc = device_get_softc(dev);
1194	if (child == sc->miibus)
1195		sc->miibus = NULL;
1196}
1197
1198static void
1199ed_pccard_tick(struct ed_softc *sc)
1200{
1201	struct mii_data *mii;
1202	int media = 0;
1203
1204	ED_ASSERT_LOCKED(sc);
1205	if (sc->miibus != NULL) {
1206		mii = device_get_softc(sc->miibus);
1207		media = mii->mii_media_status;
1208		mii_tick(mii);
1209		if (mii->mii_media_status & IFM_ACTIVE &&
1210		    media != mii->mii_media_status) {
1211			if (sc->chip_type == ED_CHIP_TYPE_DL10022) {
1212				ed_asic_outb(sc, ED_DL10022_DIAG,
1213				    (mii->mii_media_active & IFM_FDX) ?
1214				    ED_DL10022_COLLISON_DIS : 0);
1215#ifdef notyet
1216			} else if (sc->chip_type == ED_CHIP_TYPE_DL10019) {
1217				write_asic(sc, ED_DL10019_MAGIC,
1218				    (mii->mii_media_active & IFM_FDX) ?
1219				    DL19FDUPLX : 0);
1220#endif
1221			}
1222		}
1223
1224	}
1225}
1226
1227static device_method_t ed_pccard_methods[] = {
1228	/* Device interface */
1229	DEVMETHOD(device_probe,		ed_pccard_probe),
1230	DEVMETHOD(device_attach,	ed_pccard_attach),
1231	DEVMETHOD(device_detach,	ed_detach),
1232
1233	/* Bus interface */
1234	DEVMETHOD(bus_child_detached,	ed_child_detached),
1235
1236	/* MII interface */
1237	DEVMETHOD(miibus_readreg,	ed_miibus_readreg),
1238	DEVMETHOD(miibus_writereg,	ed_miibus_writereg),
1239
1240	{ 0, 0 }
1241};
1242
1243static driver_t ed_pccard_driver = {
1244	"ed",
1245	ed_pccard_methods,
1246	sizeof(struct ed_softc)
1247};
1248
1249DRIVER_MODULE(ed, pccard, ed_pccard_driver, ed_devclass, 0, 0);
1250DRIVER_MODULE(miibus, ed, miibus_driver, miibus_devclass, 0, 0);
1251MODULE_DEPEND(ed, miibus, 1, 1, 1);
1252MODULE_DEPEND(ed, ether, 1, 1, 1);
1253