if_ed_pccard.c revision 86273
1/*
2 * Copyright (c) 1995, David Greenman
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice unmodified, this list of conditions, and the following
10 *    disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: head/sys/dev/ed/if_ed_pccard.c 86273 2001-11-11 20:17:10Z imp $
28 */
29
30#include "opt_ed.h"
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/socket.h>
35#include <sys/kernel.h>
36#include <sys/conf.h>
37#include <sys/uio.h>
38
39#include <sys/module.h>
40#include <sys/bus.h>
41#include <machine/bus.h>
42#include <sys/rman.h>
43#include <machine/resource.h>
44
45#include <net/ethernet.h>
46#include <net/if.h>
47#include <net/if_arp.h>
48#include <net/if_mib.h>
49#include <net/if_media.h>
50
51#include <dev/ed/if_edreg.h>
52#include <dev/ed/if_edvar.h>
53#include <dev/pccard/pccardvar.h>
54#include <dev/pccard/pccarddevs.h>
55#ifndef ED_NO_MIIBUS
56#include <dev/mii/mii.h>
57#include <dev/mii/miivar.h>
58#endif
59
60#include "card_if.h"
61#ifndef ED_NO_MIIBUS
62/* "device miibus" required.  See GENERIC if you get errors here. */
63#include "miibus_if.h"
64
65MODULE_DEPEND(ed, miibus, 1, 1, 1);
66#endif
67
68/*
69 *      PC-Card (PCMCIA) specific code.
70 */
71static int	ed_pccard_match(device_t);
72static int	ed_pccard_probe(device_t);
73static int	ed_pccard_attach(device_t);
74static int	ed_pccard_detach(device_t);
75
76static int	ed_pccard_Linksys(device_t dev);
77static int	ed_pccard_ax88190(device_t dev);
78
79static void	ax88190_geteprom(struct ed_softc *);
80static int	ed_pccard_memwrite(device_t dev, off_t offset, u_char byte);
81#ifndef ED_NO_MIIBUS
82static void	ed_pccard_dlink_mii_reset(struct ed_softc *sc);
83static u_int	ed_pccard_dlink_mii_readbits(struct ed_softc *sc, int nbits);
84static void	ed_pccard_dlink_mii_writebits(struct ed_softc *sc, u_int val,
85    int nbits);
86#endif
87
88/*
89 *      ed_pccard_detach - unload the driver and clear the table.
90 *      XXX TODO:
91 *      This is usually called when the card is ejected, but
92 *      can be caused by a modunload of a controller driver.
93 *      The idea is to reset the driver's view of the device
94 *      and ensure that any driver entry points such as
95 *      read and write do not hang.
96 */
97static int
98ed_pccard_detach(device_t dev)
99{
100	struct ed_softc *sc = device_get_softc(dev);
101	struct ifnet *ifp = &sc->arpcom.ac_if;
102
103	if (sc->gone) {
104		device_printf(dev, "already unloaded\n");
105		return (0);
106	}
107	ed_stop(sc);
108	ifp->if_flags &= ~IFF_RUNNING;
109	ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
110	sc->gone = 1;
111	bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
112	ed_release_resources(dev);
113	return (0);
114}
115
116static const struct ed_product {
117	struct pccard_product	prod;
118	int enet_maddr;
119	unsigned char enet_vendor[3];
120	int flags;
121#define	NE2000DVF_DL10019	0x0001		/* chip is D-Link DL10019 */
122#define	NE2000DVF_AX88190	0x0002		/* chip is ASIX AX88190 */
123} ed_pccard_products[] = {
124	{ { PCMCIA_STR_AMBICOM_AMB8002T,
125	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
126	    PCMCIA_CIS_AMBICOM_AMB8002T },
127	  -1, { 0x00, 0x10, 0x7a } },
128
129	{ { PCMCIA_STR_PREMAX_PE200,
130	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
131	    PCMCIA_CIS_PREMAX_PE200 },
132	  0x07f0, { 0x00, 0x20, 0xe0 } },
133
134	{ { PCMCIA_STR_DIGITAL_DEPCMXX,
135	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
136	    PCMCIA_CIS_DIGITAL_DEPCMXX },
137	  0x0ff0, { 0x00, 0x00, 0xe8 } },
138
139	{ { PCMCIA_STR_PLANET_SMARTCOM2000,
140	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
141	    PCMCIA_CIS_PLANET_SMARTCOM2000 },
142	  0xff0, { 0x00, 0x00, 0xe8 } },
143
144	{ { PCMCIA_STR_DLINK_DE660,
145	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
146	    PCMCIA_CIS_DLINK_DE660 },
147	  -1, { 0x00, 0x80, 0xc8 } },
148
149	{ { PCMCIA_STR_RPTI_EP400,
150	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
151	    PCMCIA_CIS_RPTI_EP400 },
152	  -1, { 0x00, 0x40, 0x95 } },
153
154	{ { PCMCIA_STR_RPTI_EP401,
155	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
156	    PCMCIA_CIS_RPTI_EP401 },
157	  -1, { 0x00, 0x40, 0x95 } },
158
159	{ { PCMCIA_STR_ACCTON_EN2212,
160	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
161	    PCMCIA_CIS_ACCTON_EN2212 },
162	  0x0ff0, { 0x00, 0x00, 0xe8 } },
163
164	{ { PCMCIA_STR_SVEC_COMBOCARD,
165	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
166	    PCMCIA_CIS_SVEC_COMBOCARD },
167	  -1, { 0x00, 0xe0, 0x98 } },
168
169	{ { PCMCIA_STR_SVEC_LANCARD,
170	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
171	    PCMCIA_CIS_SVEC_LANCARD },
172	  0x7f0, { 0x00, 0xc0, 0x6c } },
173
174	{ { PCMCIA_STR_EPSON_EEN10B,
175	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_EPSON_EEN10B, 0,
176	    PCMCIA_CIS_EPSON_EEN10B },
177	  0xff0, { 0x00, 0x00, 0x48 } },
178
179	/*
180	 * You have to add new entries which contains
181	 * PCMCIA_VENDOR_INVALID and/or PCMCIA_PRODUCT_INVALID
182	 * in front of this comment.
183	 *
184	 * There are cards which use a generic vendor and product id but needs
185	 * a different handling depending on the cis_info, so ne2000_match
186	 * needs a table where the exceptions comes first and then the normal
187	 * product and vendor entries.
188	 */
189
190	{ { PCMCIA_STR_IBM_INFOMOVER,
191	    PCMCIA_VENDOR_IBM, PCMCIA_PRODUCT_IBM_INFOMOVER, 0,
192	    PCMCIA_CIS_IBM_INFOMOVER },
193	  0x0ff0, { 0x08, 0x00, 0x5a } },
194
195	{ { PCMCIA_STR_IBM_INFOMOVER,
196	    PCMCIA_VENDOR_IBM, PCMCIA_PRODUCT_IBM_INFOMOVER, 0,
197	    PCMCIA_CIS_IBM_INFOMOVER },
198	  0x0ff0, { 0x00, 0x04, 0xac } },
199
200	{ { PCMCIA_STR_IBM_INFOMOVER,
201	    PCMCIA_VENDOR_IBM, PCMCIA_PRODUCT_IBM_INFOMOVER, 0,
202	    PCMCIA_CIS_IBM_INFOMOVER },
203	  0x0ff0, { 0x00, 0x06, 0x29 } },
204
205	{ { PCMCIA_STR_KINGSTON_KNE2,		PCMCIA_VENDOR_KINGSTON,
206	    PCMCIA_PRODUCT_KINGSTON_KNE2,		0,
207	    PCMCIA_CIS_KINGSTON_KNE2 },
208	  -1, { 0, 0, 0 }, 0 },			/* XXX */
209
210	{ { PCMCIA_STR_LINKSYS_ECARD_1,
211	    PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_ECARD_1, 0,
212	    PCMCIA_CIS_LINKSYS_ECARD_1 },
213	  -1, { 0x00, 0x80, 0xc8 } },
214
215	{ { PCMCIA_STR_PLANEX_FNW3600T,
216	    PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_COMBO_ECARD, 0,
217	    PCMCIA_CIS_PLANEX_FNW3600T },
218	  -1, { 0x00, 0x90, 0xcc }, NE2000DVF_DL10019 },
219
220	{ { PCMCIA_STR_SVEC_PN650TX,
221	    PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_COMBO_ECARD, 0,
222	    PCMCIA_CIS_SVEC_PN650TX },
223	  -1, { 0x00, 0xe0, 0x98 }, NE2000DVF_DL10019 },
224
225	/*
226	 * This entry should be here so that above two cards doesn't
227	 * match with this.  FNW-3700T won't match above entries due to
228	 * MAC address check.
229	 */
230	{ { PCMCIA_STR_PLANEX_FNW3700T,
231	    PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_COMBO_ECARD, 0,
232	    PCMCIA_CIS_PLANEX_FNW3700T },
233	  -1, { 0x00, 0x90, 0xcc }, NE2000DVF_AX88190 },
234
235	{ { PCMCIA_STR_LINKSYS_ETHERFAST,
236	    PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_ETHERFAST, 0,
237	    PCMCIA_CIS_LINKSYS_ETHERFAST },
238	  -1, { 0x00, 0x80, 0xc8 }, NE2000DVF_DL10019 },
239
240	{ { PCMCIA_STR_DLINK_DE650,
241	    PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_ETHERFAST, 0,
242	    PCMCIA_CIS_DLINK_DE650 },
243	  -1, { 0x00, 0xe0, 0x98 }, NE2000DVF_DL10019 },
244
245	{ { PCMCIA_STR_MELCO_LPC2_TX,
246	    PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_ETHERFAST, 0,
247	    PCMCIA_CIS_MELCO_LPC2_TX },
248	  -1, { 0x00, 0x40, 0x26 }, NE2000DVF_DL10019 },
249
250	{ { PCMCIA_STR_LINKSYS_COMBO_ECARD,
251	    PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_COMBO_ECARD, 0,
252	    PCMCIA_CIS_LINKSYS_COMBO_ECARD },
253	  -1, { 0x00, 0x80, 0xc8 } },
254
255	{ { PCMCIA_STR_LINKSYS_TRUST_COMBO_ECARD,
256	    PCMCIA_VENDOR_LINKSYS, PCMCIA_PRODUCT_LINKSYS_TRUST_COMBO_ECARD, 0,
257	    PCMCIA_CIS_LINKSYS_TRUST_COMBO_ECARD },
258	  0x0120, { 0x20, 0x04, 0x49 } },
259
260	/*
261	 * Although the comments above say to put VENDOR/PRODUCT
262	 * INVALID IDs above this list, we need to keep this one below
263	 * the ECARD_1, or else both will match the same more-generic
264	 * entry rather than the more specific one above with proper
265	 * vendor and product IDs.
266	 */
267	{ { PCMCIA_STR_LINKSYS_ECARD_2,
268	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
269	    PCMCIA_CIS_LINKSYS_ECARD_2 },
270	  -1, { 0x00, 0x80, 0xc8 } },
271
272	/*
273	 * D-Link DE-650 has many minor versions:
274	 *
275	 *   CIS information          Manufacturer Product  Note
276	 * 1 "D-Link, DE-650"             INVALID  INVALID  white card
277	 * 2 "D-Link, DE-650, Ver 01.00"  INVALID  INVALID  became bare metal
278	 * 3 "D-Link, DE-650, Ver 01.00"   0x149    0x265   minor changed look
279	 * 4 "D-Link, DE-650, Ver 01.00"   0x149    0x265   collision LED added
280	 *
281	 * While the 1st and the 2nd types should use the "D-Link DE-650"
282	 * entry, the 3rd and the 4th types should use the "Linksys
283	 * EtherCard" entry. Therefore, this enty must be below the
284	 * LINKSYS_ECARD_1.  --itohy
285	 */
286	{ { PCMCIA_STR_DLINK_DE650,
287	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
288	    PCMCIA_CIS_DLINK_DE650 },
289	  0x0040, { 0x00, 0x80, 0xc8 } },
290
291	/*
292	 * IO-DATA PCLA/TE and later version of PCLA/T has valid
293	 * vendor/product ID and it is possible to read MAC address
294	 * using standard I/O ports.  It also read from CIS offset 0x01c0.
295	 * On the other hand, earlier version of PCLA/T doesn't have valid
296	 * vendor/product ID and MAC address must be read from CIS offset
297	 * 0x0ff0 (i.e., usual ne2000 way to read it doesn't work).
298	 * And CIS information of earlier and later version of PCLA/T are
299	 * same except fourth element.  So, for now, we place the entry for
300	 * PCLA/TE (and later version of PCLA/T) followed by entry
301	 * for the earlier version of PCLA/T (or, modify to match all CIS
302	 * information and have three or more individual entries).
303	 */
304	{ { PCMCIA_STR_IODATA_PCLATE,
305	    PCMCIA_VENDOR_IODATA, PCMCIA_PRODUCT_IODATA_PCLATE, 0,
306	    PCMCIA_CIS_IODATA_PCLATE },
307	  -1, { 0x00, 0xa0, 0xb0 } },
308
309	/*
310	 * This entry should be placed after above PCLA-TE entry.
311	 * See above comments for detail.
312	 */
313	{ { PCMCIA_STR_IODATA_PCLAT,
314	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
315	    PCMCIA_CIS_IODATA_PCLAT },
316	  0x0ff0, { 0x00, 0xa0, 0xb0 } },
317
318	{ { PCMCIA_STR_DAYNA_COMMUNICARD_E_1,
319	    PCMCIA_VENDOR_DAYNA, PCMCIA_PRODUCT_DAYNA_COMMUNICARD_E_1, 0,
320	    PCMCIA_CIS_DAYNA_COMMUNICARD_E_1 },
321	  0x0110, { 0x00, 0x80, 0x19 } },
322
323	{ { PCMCIA_STR_DAYNA_COMMUNICARD_E_2,
324	    PCMCIA_VENDOR_DAYNA, PCMCIA_PRODUCT_DAYNA_COMMUNICARD_E_2, 0,
325	    PCMCIA_CIS_DAYNA_COMMUNICARD_E_2 },
326	  -1, { 0x00, 0x80, 0x19 } },
327
328	{ { PCMCIA_STR_COREGA_ETHER_PCC_T,
329	    PCMCIA_VENDOR_COREGA, PCMCIA_PRODUCT_COREGA_ETHER_PCC_T, 0,
330	    PCMCIA_CIS_COREGA_ETHER_PCC_T },
331	  -1, { 0x00, 0x00, 0xf4 } },
332
333	{ { PCMCIA_STR_COREGA_ETHER_II_PCC_T,
334	    PCMCIA_VENDOR_COREGA, PCMCIA_PRODUCT_COREGA_ETHER_II_PCC_T, 0,
335	    PCMCIA_CIS_COREGA_ETHER_II_PCC_T },
336	  -1, { 0x00, 0x00, 0xf4 } },
337
338	{ { PCMCIA_STR_COREGA_FAST_ETHER_PCC_TX,
339	    PCMCIA_VENDOR_COREGA, PCMCIA_PRODUCT_COREGA_FAST_ETHER_PCC_TX, 0,
340	    PCMCIA_CIS_COREGA_FAST_ETHER_PCC_TX },
341	  -1, { 0x00, 0x00, 0xf4 }, NE2000DVF_DL10019 },
342
343	{ { PCMCIA_STR_COMPEX_LINKPORT_ENET_B,
344	    PCMCIA_VENDOR_COMPEX, PCMCIA_PRODUCT_COMPEX_LINKPORT_ENET_B, 0,
345	    PCMCIA_CIS_COMPEX_LINKPORT_ENET_B },
346	  0x01c0, { 0x00, 0xa0, 0x0c } },
347
348	{ { PCMCIA_STR_SMC_EZCARD,
349	    PCMCIA_VENDOR_SMC, PCMCIA_PRODUCT_SMC_EZCARD, 0,
350	    PCMCIA_CIS_SMC_EZCARD },
351	  0x01c0, { 0x00, 0xe0, 0x29 } },
352
353	{ { PCMCIA_STR_SOCKET_LP_ETHER_CF,
354	    PCMCIA_VENDOR_SOCKET, PCMCIA_PRODUCT_SOCKET_LP_ETHER_CF, 0,
355	    PCMCIA_CIS_SOCKET_LP_ETHER_CF },
356	  -1, { 0x00, 0xc0, 0x1b } },
357
358	{ { PCMCIA_STR_SOCKET_LP_ETHER,
359	    PCMCIA_VENDOR_SOCKET, PCMCIA_PRODUCT_SOCKET_LP_ETHER, 0,
360	    PCMCIA_CIS_SOCKET_LP_ETHER },
361	  -1, { 0x00, 0xc0, 0x1b } },
362
363	{ { PCMCIA_STR_XIRCOM_CFE_10,
364	    PCMCIA_VENDOR_XIRCOM, PCMCIA_PRODUCT_XIRCOM_CFE_10, 0,
365	    PCMCIA_CIS_XIRCOM_CFE_10 },
366	  -1, { 0x00, 0x10, 0xa4 } },
367
368	{ { PCMCIA_STR_MELCO_LPC3_TX,
369	    PCMCIA_VENDOR_MELCO, PCMCIA_PRODUCT_MELCO_LPC3_TX, 0,
370	    PCMCIA_CIS_MELCO_LPC3_TX },
371	  -1, { 0x00, 0x40, 0x26 }, NE2000DVF_AX88190 },
372
373	{ { PCMCIA_STR_BILLIONTON_LNT10TN,
374	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
375	    PCMCIA_CIS_BILLIONTON_LNT10TN },
376	  -1, { 0x00, 0x00, 0x00 } },
377
378	{ { PCMCIA_STR_NDC_ND5100_E,
379	    PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, 0,
380	    PCMCIA_CIS_NDC_ND5100_E },
381	  -1, { 0x00, 0x80, 0xc6 } },
382
383	{ { PCMCIA_STR_TELECOMDEVICE_TCD_HPC100,
384	    PCMCIA_VENDOR_TELECOMDEVICE, PCMCIA_PRODUCT_TELECOMDEVICE_TCD_HPC100, 0,
385	    PCMCIA_CIS_TELECOMDEVICE_TCD_HPC100 },
386	  -1, { 0x00, 0x40, 0x26 }, NE2000DVF_AX88190 },
387
388	{ { PCMCIA_STR_MACNICA_ME1_JEIDA,
389	    PCMCIA_VENDOR_MACNICA, PCMCIA_PRODUCT_MACNICA_ME1_JEIDA, 0,
390	    PCMCIA_CIS_MACNICA_ME1_JEIDA },
391	  0x00b8, { 0x08, 0x00, 0x42 } },
392
393#if 0
394    /* the rest of these are stolen from the linux pcnet pcmcia device
395       driver.  Since I don't know the manfid or cis info strings for
396       any of them, they're not compiled in until I do. */
397    { "APEX MultiCard",
398      0x0000, 0x0000, NULL, NULL, 0,
399      0x03f4, { 0x00, 0x20, 0xe5 } },
400    { "ASANTE FriendlyNet",
401      0x0000, 0x0000, NULL, NULL, 0,
402      0x4910, { 0x00, 0x00, 0x94 } },
403    { "Danpex EN-6200P2",
404      0x0000, 0x0000, NULL, NULL, 0,
405      0x0110, { 0x00, 0x40, 0xc7 } },
406    { "DataTrek NetCard",
407      0x0000, 0x0000, NULL, NULL, 0,
408      0x0ff0, { 0x00, 0x20, 0xe8 } },
409    { "Dayna CommuniCard E",
410      0x0000, 0x0000, NULL, NULL, 0,
411      0x0110, { 0x00, 0x80, 0x19 } },
412    { "EP-210 Ethernet",
413      0x0000, 0x0000, NULL, NULL, 0,
414      0x0110, { 0x00, 0x40, 0x33 } },
415    { "ELECOM Laneed LD-CDWA",
416      0x0000, 0x0000, NULL, NULL, 0,
417      0x00b8, { 0x08, 0x00, 0x42 } },
418    { "Grey Cell GCS2220",
419      0x0000, 0x0000, NULL, NULL, 0,
420      0x0000, { 0x00, 0x47, 0x43 } },
421    { "Hypertec Ethernet",
422      0x0000, 0x0000, NULL, NULL, 0,
423      0x01c0, { 0x00, 0x40, 0x4c } },
424    { "IBM CCAE",
425      0x0000, 0x0000, NULL, NULL, 0,
426      0x0ff0, { 0x08, 0x00, 0x5a } },
427    { "IBM CCAE",
428      0x0000, 0x0000, NULL, NULL, 0,
429      0x0ff0, { 0x00, 0x04, 0xac } },
430    { "IBM CCAE",
431      0x0000, 0x0000, NULL, NULL, 0,
432      0x0ff0, { 0x00, 0x06, 0x29 } },
433    { "IBM FME",
434      0x0000, 0x0000, NULL, NULL, 0,
435      0x0374, { 0x00, 0x04, 0xac } },
436    { "IBM FME",
437      0x0000, 0x0000, NULL, NULL, 0,
438      0x0374, { 0x08, 0x00, 0x5a } },
439    { "Katron PE-520",
440      0x0000, 0x0000, NULL, NULL, 0,
441      0x0110, { 0x00, 0x40, 0xf6 } },
442    { "Kingston KNE-PCM/x",
443      0x0000, 0x0000, NULL, NULL, 0,
444      0x0ff0, { 0x00, 0xc0, 0xf0 } },
445    { "Kingston KNE-PCM/x",
446      0x0000, 0x0000, NULL, NULL, 0,
447      0x0ff0, { 0xe2, 0x0c, 0x0f } },
448    { "Kingston KNE-PC2",
449      0x0000, 0x0000, NULL, NULL, 0,
450      0x0180, { 0x00, 0xc0, 0xf0 } },
451    { "Longshine LCS-8534",
452      0x0000, 0x0000, NULL, NULL, 0,
453      0x0000, { 0x08, 0x00, 0x00 } },
454    { "Maxtech PCN2000",
455      0x0000, 0x0000, NULL, NULL, 0,
456      0x5000, { 0x00, 0x00, 0xe8 } },
457    { "NDC Instant-Link",
458      0x0000, 0x0000, NULL, NULL, 0,
459      0x003a, { 0x00, 0x80, 0xc6 } },
460    { "NE2000 Compatible",
461      0x0000, 0x0000, NULL, NULL, 0,
462      0x0ff0, { 0x00, 0xa0, 0x0c } },
463    { "Network General Sniffer",
464      0x0000, 0x0000, NULL, NULL, 0,
465      0x0ff0, { 0x00, 0x00, 0x65 } },
466    { "Panasonic VEL211",
467      0x0000, 0x0000, NULL, NULL, 0,
468      0x0ff0, { 0x00, 0x80, 0x45 } },
469    { "SCM Ethernet",
470      0x0000, 0x0000, NULL, NULL, 0,
471      0x0ff0, { 0x00, 0x20, 0xcb } },
472    { "Socket EA",
473      0x0000, 0x0000, NULL, NULL, 0,
474      0x4000, { 0x00, 0xc0, 0x1b } },
475    { "Volktek NPL-402CT",
476      0x0000, 0x0000, NULL, NULL, 0,
477      0x0060, { 0x00, 0x40, 0x05 } },
478#endif
479
480	{ { PCMCIA_STR_ALLIEDTELESIS_LA_PCM,
481	    PCMCIA_VENDOR_ALLIEDTELESIS, PCMCIA_PRODUCT_ALLIEDTELESIS_LA_PCM, 0,
482	    PCMCIA_CIS_ALLIEDTELESIS_LA_PCM },
483	  0x0ff0, { 0x00, 0x00, 0xf4 } },
484
485};
486
487static int
488ed_pccard_match(device_t dev)
489{
490	const struct pccard_product *pp;
491
492	if ((pp = pccard_product_lookup(dev,
493	    (const struct pccard_product *) ed_pccard_products,
494	    sizeof(ed_pccard_products[0]), NULL)) != NULL) {
495		device_set_desc(dev, pp->pp_name);
496		return 0;
497	}
498	return EIO;
499}
500
501/*
502 * Probe framework for pccards.  Replicates the standard framework,
503 * minus the pccard driver registration and ignores the ether address
504 * supplied (from the CIS), relying on the probe to find it instead.
505 */
506static int
507ed_pccard_probe(device_t dev)
508{
509	int	error;
510	int	flags = device_get_flags(dev);
511
512	if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_AX88190) {
513		error = ed_pccard_ax88190(dev);
514		goto end2;
515	}
516
517	error = ed_probe_Novell(dev, 0, flags);
518	if (error == 0)
519		goto end;
520	ed_release_resources(dev);
521
522	error = ed_probe_WD80x3(dev, 0, flags);
523	if (error == 0)
524		goto end;
525	ed_release_resources(dev);
526	goto end2;
527
528end:
529	if (ED_FLAGS_GETTYPE(flags) & ED_FLAGS_LINKSYS)
530		ed_pccard_Linksys(dev);
531end2:
532	if (error == 0)
533		error = ed_alloc_irq(dev, 0, 0);
534
535	ed_release_resources(dev);
536	return (error);
537}
538
539static int
540ed_pccard_attach(device_t dev)
541{
542	int error;
543	int	flags = device_get_flags(dev);
544	int i;
545	struct ed_softc *sc = device_get_softc(dev);
546	u_char sum;
547	u_char ether_addr[ETHER_ADDR_LEN];
548
549	if (sc->port_used > 0)
550		ed_alloc_port(dev, sc->port_rid, sc->port_used);
551	if (sc->mem_used)
552		ed_alloc_memory(dev, sc->mem_rid, sc->mem_used);
553	ed_alloc_irq(dev, sc->irq_rid, 0);
554
555	error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
556			       edintr, sc, &sc->irq_handle);
557	if (error) {
558		printf("setup intr failed %d \n", error);
559		ed_release_resources(dev);
560		return (error);
561	}
562
563	if (sc->vendor != ED_VENDOR_LINKSYS) {
564		pccard_get_ether(dev, ether_addr);
565		for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++)
566			sum |= ether_addr[i];
567		if (sum)
568			bcopy(ether_addr, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
569	}
570
571	error = ed_attach(sc, device_get_unit(dev), flags);
572#ifndef ED_NO_MIIBUS
573	if (error == 0 && sc->vendor == ED_VENDOR_LINKSYS) {
574		/* Probe for an MII bus, but ignore errors. */
575		ed_pccard_dlink_mii_reset(sc);
576		sc->mii_readbits = ed_pccard_dlink_mii_readbits;
577		sc->mii_writebits = ed_pccard_dlink_mii_writebits;
578		mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd,
579		    ed_ifmedia_sts);
580	}
581#endif
582
583	return (error);
584}
585
586static void
587ax88190_geteprom(struct ed_softc *sc)
588{
589	int prom[16],i;
590	u_char tmp;
591	struct {
592		unsigned char offset, value;
593	} pg_seq[] = {
594		{ED_P0_CR, ED_CR_RD2|ED_CR_STP},/* Select Page0 */
595		{ED_P0_DCR, 0x01},
596		{ED_P0_RBCR0, 0x00},		/* Clear the count regs. */
597		{ED_P0_RBCR1, 0x00},
598		{ED_P0_IMR, 0x00},		/* Mask completion irq. */
599		{ED_P0_ISR, 0xff},
600		{ED_P0_RCR, ED_RCR_MON | ED_RCR_INTT}, /* Set To Monitor */
601		{ED_P0_TCR, ED_TCR_LB0},	/* loopback mode. */
602		{ED_P0_RBCR0, 32},
603		{ED_P0_RBCR1, 0x00},
604		{ED_P0_RSAR0, 0x00},
605		{ED_P0_RSAR1, 0x04},
606		{ED_P0_CR ,ED_CR_RD0 | ED_CR_STA},
607	};
608
609	/* Reset Card */
610	tmp = ed_asic_inb(sc, ED_NOVELL_RESET);
611	ed_asic_outb(sc, ED_NOVELL_RESET, tmp);
612	DELAY(5000);
613	ed_asic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
614	DELAY(5000);
615
616	/* Card Settings */
617	for (i = 0; i < sizeof(pg_seq) / sizeof(pg_seq[0]); i++)
618		ed_nic_outb(sc, pg_seq[i].offset, pg_seq[i].value);
619
620	/* Get Data */
621	for (i = 0; i < 16; i++)
622		prom[i] = ed_asic_inb(sc, 0);
623	sc->arpcom.ac_enaddr[0] = prom[0] & 0xff;
624	sc->arpcom.ac_enaddr[1] = prom[0] >> 8;
625	sc->arpcom.ac_enaddr[2] = prom[1] & 0xff;
626	sc->arpcom.ac_enaddr[3] = prom[1] >> 8;
627	sc->arpcom.ac_enaddr[4] = prom[2] & 0xff;
628	sc->arpcom.ac_enaddr[5] = prom[2] >> 8;
629}
630
631static int
632ed_pccard_memwrite(device_t dev, off_t offset, u_char byte)
633{
634	int cis_rid;
635	struct resource *cis;
636
637	cis_rid = 0;
638	cis = bus_alloc_resource(dev, SYS_RES_MEMORY, &cis_rid, 0, ~0,
639	    4 << 10, RF_ACTIVE | RF_SHAREABLE);
640	if (cis == NULL)
641		return (ENXIO);
642	CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY,
643	    cis_rid, PCCARD_A_MEM_ATTR);
644
645	bus_space_write_1(rman_get_bustag(cis), rman_get_bushandle(cis),
646	    offset, byte);
647
648	bus_deactivate_resource(dev, SYS_RES_MEMORY, cis_rid, cis);
649	bus_release_resource(dev, SYS_RES_MEMORY, cis_rid, cis);
650
651	return (0);
652}
653
654/*
655 * Probe the Ethernet MAC addrees for PCMCIA Linksys EtherFast 10/100
656 * and compatible cards (DL10019C Ethernet controller).
657 *
658 * Note: The PAO patches try to use more memory for the card, but that
659 * seems to fail for my card.  A future optimization would add this back
660 * conditionally.
661 */
662static int
663ed_pccard_Linksys(device_t dev)
664{
665	struct ed_softc *sc = device_get_softc(dev);
666	u_char sum;
667	int i;
668
669	/*
670	 * Linksys registers(offset from ASIC base)
671	 *
672	 * 0x04-0x09 : Physical Address Register 0-5 (PAR0-PAR5)
673	 * 0x0A      : Card ID Register (CIR)
674	 * 0x0B      : Check Sum Register (SR)
675	 */
676	for (sum = 0, i = 0x04; i < 0x0c; i++)
677		sum += ed_asic_inb(sc, i);
678	if (sum != 0xff)
679		return (0);		/* invalid DL10019C */
680	for (i = 0; i < ETHER_ADDR_LEN; i++) {
681		sc->arpcom.ac_enaddr[i] = ed_asic_inb(sc, 0x04 + i);
682	}
683
684	ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
685	sc->isa16bit = 1;
686	sc->vendor = ED_VENDOR_LINKSYS;
687	sc->type = ED_TYPE_NE2000;
688	sc->type_str = "Linksys";
689
690	return (1);
691}
692
693/*
694 * Special setup for AX88190
695 */
696static int
697ed_pccard_ax88190(device_t dev)
698{
699	int	error;
700	int	flags = device_get_flags(dev);
701	int	iobase;
702	struct	ed_softc *sc = device_get_softc(dev);
703
704	/* Allocate the port resource during setup. */
705	error = ed_alloc_port(dev, 0, ED_NOVELL_IO_PORTS);
706	if (error)
707		return (error);
708
709	sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
710	sc->nic_offset  = ED_NOVELL_NIC_OFFSET;
711	sc->chip_type = ED_CHIP_TYPE_AX88190;
712
713	/*
714	 * Set Attribute Memory IOBASE Register
715	 */
716	iobase = rman_get_start(sc->port_res);
717	ed_pccard_memwrite(dev, ED_AX88190_IOBASE0, iobase & 0xff);
718	ed_pccard_memwrite(dev, ED_AX88190_IOBASE1, (iobase >> 8) & 0xff);
719	ax88190_geteprom(sc);
720	ed_release_resources(dev);
721	error = ed_probe_Novell(dev, 0, flags);
722	return (error);
723}
724
725#ifndef ED_NO_MIIBUS
726/* MII bit-twiddling routines for cards using Dlink chipset */
727#define DLINK_MIISET(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \
728    ed_asic_inb(sc, ED_DLINK_MIIBUS) | (x))
729#define DLINK_MIICLR(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \
730    ed_asic_inb(sc, ED_DLINK_MIIBUS) & ~(x))
731
732static void
733ed_pccard_dlink_mii_reset(sc)
734	struct ed_softc *sc;
735{
736	ed_asic_outb(sc, ED_DLINK_MIIBUS, 0);
737	DELAY(10);
738	DLINK_MIISET(sc, ED_DLINK_MII_RESET2);
739	DELAY(10);
740	DLINK_MIISET(sc, ED_DLINK_MII_RESET1);
741	DELAY(10);
742	DLINK_MIICLR(sc, ED_DLINK_MII_RESET1);
743	DELAY(10);
744	DLINK_MIICLR(sc, ED_DLINK_MII_RESET2);
745	DELAY(10);
746}
747
748static void
749ed_pccard_dlink_mii_writebits(sc, val, nbits)
750	struct ed_softc *sc;
751	u_int val;
752	int nbits;
753{
754	int i;
755
756	DLINK_MIISET(sc, ED_DLINK_MII_DIROUT);
757
758	for (i = nbits - 1; i >= 0; i--) {
759		if ((val >> i) & 1)
760			DLINK_MIISET(sc, ED_DLINK_MII_DATAOUT);
761		else
762			DLINK_MIICLR(sc, ED_DLINK_MII_DATAOUT);
763		DELAY(10);
764		DLINK_MIISET(sc, ED_DLINK_MII_CLK);
765		DELAY(10);
766		DLINK_MIICLR(sc, ED_DLINK_MII_CLK);
767		DELAY(10);
768	}
769}
770
771static u_int
772ed_pccard_dlink_mii_readbits(sc, nbits)
773	struct ed_softc *sc;
774	int nbits;
775{
776	int i;
777	u_int val = 0;
778
779	DLINK_MIICLR(sc, ED_DLINK_MII_DIROUT);
780
781	for (i = nbits - 1; i >= 0; i--) {
782		DLINK_MIISET(sc, ED_DLINK_MII_CLK);
783		DELAY(10);
784		val <<= 1;
785		if (ed_asic_inb(sc, ED_DLINK_MIIBUS) & ED_DLINK_MII_DATATIN)
786			val++;
787		DLINK_MIICLR(sc, ED_DLINK_MII_CLK);
788		DELAY(10);
789	}
790
791	return val;
792}
793#endif
794
795static device_method_t ed_pccard_methods[] = {
796	/* Device interface */
797	DEVMETHOD(device_probe,		pccard_compat_probe),
798	DEVMETHOD(device_attach,	pccard_compat_attach),
799	DEVMETHOD(device_detach,	ed_pccard_detach),
800
801#ifndef ED_NO_MIIBUS
802	/* Bus interface */
803	DEVMETHOD(bus_child_detached,	ed_child_detached),
804
805	/* MII interface */
806	DEVMETHOD(miibus_readreg,	ed_miibus_readreg),
807	DEVMETHOD(miibus_writereg,	ed_miibus_writereg),
808#endif
809
810	/* Card interface */
811	DEVMETHOD(card_compat_match,	ed_pccard_match),
812	DEVMETHOD(card_compat_probe,	ed_pccard_probe),
813	DEVMETHOD(card_compat_attach,	ed_pccard_attach),
814	{ 0, 0 }
815};
816
817static driver_t ed_pccard_driver = {
818	"ed",
819	ed_pccard_methods,
820	sizeof(struct ed_softc)
821};
822
823DRIVER_MODULE(if_ed, pccard, ed_pccard_driver, ed_devclass, 0, 0);
824#ifndef ED_NO_MIIBUS
825DRIVER_MODULE(miibus, ed, miibus_driver, miibus_devclass, 0, 0);
826#endif
827