xref: /netbsd-src/sys/dev/pcmcia/if_ep_pcmcia.c (revision 8bc54e5be648e06e7c6b48f7611f8bccfda032d4)
1*8bc54e5bSmsaitoh /*	$NetBSD: if_ep_pcmcia.c,v 1.64 2016/07/07 06:55:42 msaitoh Exp $	*/
24c88513dSthorpej 
34c88513dSthorpej /*-
48ccc9500Smycroft  * Copyright (c) 1998, 2000, 2004 The NetBSD Foundation, Inc.
54c88513dSthorpej  * All rights reserved.
64c88513dSthorpej  *
74c88513dSthorpej  * This code is derived from software contributed to The NetBSD Foundation
84c88513dSthorpej  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
98ccc9500Smycroft  * NASA Ames Research Center, and by Charles M. Hannum.
104c88513dSthorpej  *
114c88513dSthorpej  * Redistribution and use in source and binary forms, with or without
124c88513dSthorpej  * modification, are permitted provided that the following conditions
134c88513dSthorpej  * are met:
144c88513dSthorpej  * 1. Redistributions of source code must retain the above copyright
154c88513dSthorpej  *    notice, this list of conditions and the following disclaimer.
164c88513dSthorpej  * 2. Redistributions in binary form must reproduce the above copyright
174c88513dSthorpej  *    notice, this list of conditions and the following disclaimer in the
184c88513dSthorpej  *    documentation and/or other materials provided with the distribution.
194c88513dSthorpej  *
204c88513dSthorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
214c88513dSthorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
224c88513dSthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
234c88513dSthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
244c88513dSthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
254c88513dSthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
264c88513dSthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
274c88513dSthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
284c88513dSthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
294c88513dSthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
304c88513dSthorpej  * POSSIBILITY OF SUCH DAMAGE.
314c88513dSthorpej  */
32c66b8643Sthorpej 
33c66b8643Sthorpej /*
34c66b8643Sthorpej  * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
35c66b8643Sthorpej  *
36c66b8643Sthorpej  * Redistribution and use in source and binary forms, with or without
37c66b8643Sthorpej  * modification, are permitted provided that the following conditions
38c66b8643Sthorpej  * are met:
39c66b8643Sthorpej  * 1. Redistributions of source code must retain the above copyright
40c66b8643Sthorpej  *    notice, this list of conditions and the following disclaimer.
41c66b8643Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
42c66b8643Sthorpej  *    notice, this list of conditions and the following disclaimer in the
43c66b8643Sthorpej  *    documentation and/or other materials provided with the distribution.
44c66b8643Sthorpej  * 3. All advertising materials mentioning features or use of this software
45c66b8643Sthorpej  *    must display the following acknowledgement:
46c66b8643Sthorpej  *	This product includes software developed by Marc Horowitz.
47c66b8643Sthorpej  * 4. The name of the author may not be used to endorse or promote products
48c66b8643Sthorpej  *    derived from this software without specific prior written permission.
49c66b8643Sthorpej  *
50c66b8643Sthorpej  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
51c66b8643Sthorpej  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
52c66b8643Sthorpej  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
53c66b8643Sthorpej  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
54c66b8643Sthorpej  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
55c66b8643Sthorpej  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
56c66b8643Sthorpej  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
57c66b8643Sthorpej  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58c66b8643Sthorpej  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
59c66b8643Sthorpej  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60c66b8643Sthorpej  */
61c66b8643Sthorpej 
62ab5d9d2bSlukem #include <sys/cdefs.h>
63*8bc54e5bSmsaitoh __KERNEL_RCSID(0, "$NetBSD: if_ep_pcmcia.c,v 1.64 2016/07/07 06:55:42 msaitoh Exp $");
64ab5d9d2bSlukem 
65c66b8643Sthorpej #include <sys/param.h>
66c66b8643Sthorpej #include <sys/systm.h>
67c66b8643Sthorpej #include <sys/mbuf.h>
68c66b8643Sthorpej #include <sys/socket.h>
69c66b8643Sthorpej #include <sys/ioctl.h>
70c66b8643Sthorpej #include <sys/errno.h>
71c66b8643Sthorpej #include <sys/syslog.h>
72c66b8643Sthorpej #include <sys/select.h>
73c66b8643Sthorpej #include <sys/device.h>
74c66b8643Sthorpej 
75c66b8643Sthorpej #include <net/if.h>
76c66b8643Sthorpej #include <net/if_dl.h>
77c66b8643Sthorpej #include <net/if_ether.h>
78c66b8643Sthorpej #include <net/if_media.h>
79c66b8643Sthorpej 
80a2a38285Sad #include <sys/cpu.h>
81a2a38285Sad #include <sys/bus.h>
82a2a38285Sad #include <sys/intr.h>
83c66b8643Sthorpej 
84b170caf7Sthorpej #include <dev/mii/miivar.h>
85b170caf7Sthorpej 
86c66b8643Sthorpej #include <dev/ic/elink3var.h>
87c66b8643Sthorpej #include <dev/ic/elink3reg.h>
88c66b8643Sthorpej 
89c66b8643Sthorpej #include <dev/pcmcia/pcmciareg.h>
90c66b8643Sthorpej #include <dev/pcmcia/pcmciavar.h>
91e3bc2915Schristos #include <dev/pcmcia/pcmciadevs.h>
92c66b8643Sthorpej 
9391ca465cSchristos int	ep_pcmcia_match(device_t, cfdata_t, void *);
9491ca465cSchristos void	ep_pcmcia_attach(device_t, device_t, void *);
9591ca465cSchristos int	ep_pcmcia_detach(device_t, int);
96c66b8643Sthorpej 
9718db93c7Sperry int	ep_pcmcia_get_enaddr(struct pcmcia_tuple *, void *);
9818db93c7Sperry int	ep_pcmcia_enable(struct ep_softc *);
9918db93c7Sperry void	ep_pcmcia_disable(struct ep_softc *);
100c66b8643Sthorpej 
10118db93c7Sperry void	ep_pcmcia_disable1(struct ep_softc *);
1025c85ae87Sthorpej 
103c66b8643Sthorpej struct ep_pcmcia_softc {
104c66b8643Sthorpej 	struct ep_softc sc_ep;			/* real "ep" softc */
105c66b8643Sthorpej 
106c66b8643Sthorpej 	/* PCMCIA-specific goo */
107c66b8643Sthorpej 	struct pcmcia_io_handle sc_pcioh;	/* PCMCIA i/o space info */
108c66b8643Sthorpej 	int sc_io_window;			/* our i/o window */
109c66b8643Sthorpej 	struct pcmcia_function *sc_pf;		/* our PCMCIA function */
110c66b8643Sthorpej };
111c66b8643Sthorpej 
11291ca465cSchristos CFATTACH_DECL_NEW(ep_pcmcia, sizeof(struct ep_pcmcia_softc),
113b75a007dSthorpej     ep_pcmcia_match, ep_pcmcia_attach, ep_pcmcia_detach, ep_activate);
114c66b8643Sthorpej 
115942a54e0Scgd const struct ep_pcmcia_product {
116942a54e0Scgd 	struct pcmcia_product epp_product;
1174c88513dSthorpej 	u_short		epp_chipset;	/* 3Com chipset used */
1184c88513dSthorpej 	int		epp_flags;	/* initial softc flags */
1194c88513dSthorpej } ep_pcmcia_products[] = {
120adbea351Smycroft 	{ { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3C562,
121adbea351Smycroft 	    PCMCIA_CIS_INVALID },
122942a54e0Scgd 	  ELINK_CHIPSET_3C509, 0 },
1234c88513dSthorpej 
124adbea351Smycroft 	{ { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3C589,
125adbea351Smycroft 	    PCMCIA_CIS_INVALID },
126942a54e0Scgd 	  ELINK_CHIPSET_3C509, 0 },
127b6a56aacSmarc 
128adbea351Smycroft 	{ { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556,
129adbea351Smycroft 	    PCMCIA_CIS_INVALID },
130942a54e0Scgd 	  ELINK_CHIPSET_3C509, 0 },
13136224362Stron 
132adbea351Smycroft 	{ { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556INT,
133adbea351Smycroft 	    PCMCIA_CIS_INVALID },
134942a54e0Scgd 	  ELINK_CHIPSET_3C509, 0 },
1356bfd748bSthorpej 
136adbea351Smycroft 	{ { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3C574,
137adbea351Smycroft 	    PCMCIA_CIS_INVALID },
138942a54e0Scgd 	  ELINK_CHIPSET_ROADRUNNER, ELINK_FLAGS_MII },
139eda20693Sthorpej 
140adbea351Smycroft 	{ { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CCFEM556BI,
141adbea351Smycroft 	    PCMCIA_CIS_INVALID },
142942a54e0Scgd 	  ELINK_CHIPSET_ROADRUNNER, ELINK_FLAGS_MII },
143942a54e0Scgd 
144adbea351Smycroft 	{ { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3C1,
145adbea351Smycroft 	    PCMCIA_CIS_INVALID },
1465402c76dScgd 	  ELINK_CHIPSET_3C509, 0 },
1474c88513dSthorpej };
148adbea351Smycroft const size_t ep_pcmcia_nproducts =
149adbea351Smycroft     sizeof(ep_pcmcia_products) / sizeof(ep_pcmcia_products[0]);
1504c88513dSthorpej 
151c66b8643Sthorpej int
ep_pcmcia_match(device_t parent,cfdata_t match,void * aux)15291ca465cSchristos ep_pcmcia_match(device_t parent, cfdata_t match, void *aux)
153c66b8643Sthorpej {
154c66b8643Sthorpej 	struct pcmcia_attach_args *pa = aux;
155c66b8643Sthorpej 
156adbea351Smycroft 	/* This is to differentiate the serial function of some cards. */
157adbea351Smycroft 	if (pa->pf->function != PCMCIA_FUNCTION_NETWORK)
15891ca465cSchristos 		return 0;
159c66b8643Sthorpej 
160adbea351Smycroft 	if (pcmcia_product_lookup(pa, ep_pcmcia_products, ep_pcmcia_nproducts,
161adbea351Smycroft 	    sizeof(ep_pcmcia_products[0]), NULL))
16291ca465cSchristos 		return 1;
16391ca465cSchristos 	return 0;
164c66b8643Sthorpej }
165c66b8643Sthorpej 
166c66b8643Sthorpej int
ep_pcmcia_enable(struct ep_softc * sc)16791ca465cSchristos ep_pcmcia_enable(struct ep_softc *sc)
168c66b8643Sthorpej {
169c66b8643Sthorpej 	struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
170b01ada14Smarc 	struct pcmcia_function *pf = psc->sc_pf;
171c7573d51Senami 	int error;
172c66b8643Sthorpej 
173c66b8643Sthorpej 	/* establish the interrupt. */
174b01ada14Smarc 	sc->sc_ih = pcmcia_intr_establish(pf, IPL_NET, epintr, sc);
17570ca4b2fSmycroft 	if (!sc->sc_ih)
17691ca465cSchristos 		return EIO;
177c66b8643Sthorpej 
17870ca4b2fSmycroft 	error = pcmcia_function_enable(pf);
17970ca4b2fSmycroft 	if (error) {
1802ae40d3eSmycroft 		pcmcia_intr_disestablish(pf, sc->sc_ih);
181d11fb31eSmycroft 		sc->sc_ih = 0;
18291ca465cSchristos 		return error;
1832ae40d3eSmycroft 	}
1842ae40d3eSmycroft 
185b6a56aacSmarc 	if ((psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3C562) ||
18636224362Stron 	    (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556) ||
18736224362Stron 	    (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556INT)) {
188b01ada14Smarc 		int reg;
189b01ada14Smarc 
190b01ada14Smarc 		/* turn off the serial-disable bit */
191b01ada14Smarc 
192b01ada14Smarc 		reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
193b01ada14Smarc 		if (reg & 0x08) {
194b01ada14Smarc 			reg &= ~0x08;
195b01ada14Smarc 			pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
196b01ada14Smarc 		}
197b01ada14Smarc 
198b01ada14Smarc 	}
199b01ada14Smarc 
20091ca465cSchristos 	return 0;
201c66b8643Sthorpej }
202c66b8643Sthorpej 
203c66b8643Sthorpej void
ep_pcmcia_disable(struct ep_softc * sc)20491ca465cSchristos ep_pcmcia_disable(struct ep_softc *sc)
205c66b8643Sthorpej {
206c66b8643Sthorpej 	struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
207c66b8643Sthorpej 
2085c85ae87Sthorpej 	pcmcia_function_disable(psc->sc_pf);
2099092e2c9Smycroft 	pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih);
21070ca4b2fSmycroft 	sc->sc_ih = 0;
2115c85ae87Sthorpej }
2125c85ae87Sthorpej 
2135c85ae87Sthorpej void
ep_pcmcia_attach(device_t parent,device_t self,void * aux)21491ca465cSchristos ep_pcmcia_attach(device_t parent, device_t self, void *aux)
215c66b8643Sthorpej {
21691ca465cSchristos 	struct ep_pcmcia_softc *psc = device_private(self);
217c66b8643Sthorpej 	struct ep_softc *sc = &psc->sc_ep;
218c66b8643Sthorpej 	struct pcmcia_attach_args *pa = aux;
219c66b8643Sthorpej 	struct pcmcia_config_entry *cfe;
220942a54e0Scgd 	const struct ep_pcmcia_product *epp;
221c66b8643Sthorpej 	u_int8_t myla[ETHER_ADDR_LEN];
2226bfd748bSthorpej 	u_int8_t *enaddr = NULL;
2234c88513dSthorpej 	int i;
22470ca4b2fSmycroft 	int error;
225c66b8643Sthorpej 
22691ca465cSchristos 	sc->sc_dev = self;
227c66b8643Sthorpej 	psc->sc_pf = pa->pf;
228c66b8643Sthorpej 
2292ae40d3eSmycroft 	SIMPLEQ_FOREACH(cfe, &pa->pf->cfe_head, cfe_list) {
2302ae40d3eSmycroft 		if (cfe->num_memspace != 0)
2312ae40d3eSmycroft 			continue;
2322ae40d3eSmycroft 		if (cfe->num_iospace != 1)
2332ae40d3eSmycroft 			continue;
234c66b8643Sthorpej 
235c66b8643Sthorpej 		if (pa->product == PCMCIA_PRODUCT_3COM_3C562) {
236441bea91Schristos 			/*
237441bea91Schristos 			 * the 3c562 can only use 0x??00-0x??7f
238441bea91Schristos 			 * according to the Linux driver
239441bea91Schristos 			 */
240071d0cb3Schristos 
241071d0cb3Schristos 			/*
242071d0cb3Schristos 			 * 3c562 i/o may decodes address line not only A0-3
243071d0cb3Schristos 			 * but also A7.  Anyway, we must sweep at most
244071d0cb3Schristos 			 * [0x0000, 0x0100).  The address higher is given by a
245071d0cb3Schristos 			 * pcmcia bridge.  But pcmcia bus-space allocation
246071d0cb3Schristos 			 * function implies cards will decode 10-bit address
247071d0cb3Schristos 			 * line.  So we must search [0x0000, 0x0400).
248071d0cb3Schristos 			 *
249071d0cb3Schristos 			 * XXX: We must not check the bunch of I/O space range
250071d0cb3Schristos 			 * [0x400*n, 0x300 + 0x400*n) because they are
251071d0cb3Schristos 			 * reserved for legacy ISA devices and their alias
252071d0cb3Schristos 			 * images on PC/AT architecture.
253071d0cb3Schristos 			 */
254071d0cb3Schristos 			for (i = 0x0300; i < 0x0380; i += 0x10) {
2552ae40d3eSmycroft 				if (pcmcia_io_alloc(pa->pf, i,
2562ae40d3eSmycroft 				    cfe->iospace[0].length,
2572ae40d3eSmycroft 				    cfe->iospace[0].length,
2582ae40d3eSmycroft 				    &psc->sc_pcioh) == 0)
259c66b8643Sthorpej 					break;
260c66b8643Sthorpej 			}
2612ae40d3eSmycroft 			if (i != 0x0380)
2622ae40d3eSmycroft 				break;
263c66b8643Sthorpej 		} else {
2642ae40d3eSmycroft 			if (pcmcia_io_alloc(pa->pf, cfe->iospace[0].start,
2652ae40d3eSmycroft 			    cfe->iospace[0].length, cfe->iospace[0].length,
2662ae40d3eSmycroft 			    &psc->sc_pcioh) == 0)
2672ae40d3eSmycroft 				break;
2682ae40d3eSmycroft 		}
2692ae40d3eSmycroft 	}
2702ae40d3eSmycroft 	if (!cfe) {
271bebbf57bScegger 		aprint_error_dev(self, "failed to allocate I/O space\n");
272c7573d51Senami 		goto ioalloc_failed;
273c7573d51Senami 	}
274c66b8643Sthorpej 
275c66b8643Sthorpej 	sc->sc_iot = psc->sc_pcioh.iot;
276c66b8643Sthorpej 	sc->sc_ioh = psc->sc_pcioh.ioh;
277c66b8643Sthorpej 
2782ae40d3eSmycroft 	/* Enable the card. */
2792ae40d3eSmycroft 	pcmcia_function_init(pa->pf, cfe);
2802ae40d3eSmycroft 
281c66b8643Sthorpej 	if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
282c8180f49Smycroft 	    PCMCIA_WIDTH_AUTO : PCMCIA_WIDTH_IO8), &psc->sc_pcioh,
283ebed70c6Smycroft 	    &psc->sc_io_window)) {
284bebbf57bScegger 		aprint_error_dev(self, "can't map i/o space\n");
285c7573d51Senami 		goto iomap_failed;
286c66b8643Sthorpej 	}
2876bfd748bSthorpej 
28870ca4b2fSmycroft 	error = ep_pcmcia_enable(sc);
28970ca4b2fSmycroft 	if (error)
2902ae40d3eSmycroft 		goto enable_failed;
2912ae40d3eSmycroft 	sc->enabled = 1;
2922ae40d3eSmycroft 
2936bfd748bSthorpej 	switch (pa->product) {
2946bfd748bSthorpej 	case PCMCIA_PRODUCT_3COM_3C562:
295441bea91Schristos 		/*
296441bea91Schristos 		 * 3c562a-c use this; 3c562d does it in the regular way.
297441bea91Schristos 		 * we might want to check the revision and produce a warning
298441bea91Schristos 		 * in the future.
299441bea91Schristos 		 */
3006bfd748bSthorpej 		/* FALLTHROUGH */
3016bfd748bSthorpej 	case PCMCIA_PRODUCT_3COM_3C574:
302eda20693Sthorpej 	case PCMCIA_PRODUCT_3COM_3CCFEM556BI:
3036bfd748bSthorpej 		/*
3046bfd748bSthorpej 		 * Apparently, some 3c574s do it this way, as well.
3056bfd748bSthorpej 		 */
3066bfd748bSthorpej 		if (pcmcia_scan_cis(parent, ep_pcmcia_get_enaddr, myla))
307c66b8643Sthorpej 			enaddr = myla;
3086bfd748bSthorpej 		break;
309c66b8643Sthorpej 	}
310c66b8643Sthorpej 
311*8bc54e5bSmsaitoh 	epp = pcmcia_product_lookup(pa, ep_pcmcia_products,
312*8bc54e5bSmsaitoh 	    ep_pcmcia_nproducts, sizeof(ep_pcmcia_products[0]), NULL);
313adbea351Smycroft 	if (!epp)
3144c88513dSthorpej 		panic("ep_pcmcia_attach: impossible");
315c66b8643Sthorpej 
316c9ee8bf3Sthorpej 	sc->bustype = ELINK_BUS_PCMCIA;
317c9ee8bf3Sthorpej 	sc->ep_flags = epp->epp_flags;
318c9ee8bf3Sthorpej 
319c66b8643Sthorpej 	sc->enable = ep_pcmcia_enable;
320c66b8643Sthorpej 	sc->disable = ep_pcmcia_disable;
321c66b8643Sthorpej 
322285bec82Smycroft 	if (epconfig(sc, epp->epp_chipset, enaddr))
323bebbf57bScegger 		aprint_error_dev(self, "couldn't configure controller\n");
324c66b8643Sthorpej 
325c66b8643Sthorpej 	sc->enabled = 0;
3262ae40d3eSmycroft 	ep_pcmcia_disable(sc);
327c7573d51Senami 	return;
328c7573d51Senami 
329c7573d51Senami enable_failed:
3302ae40d3eSmycroft 	pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
3312ae40d3eSmycroft iomap_failed:
3322ae40d3eSmycroft 	pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
3332ae40d3eSmycroft ioalloc_failed:
334c7573d51Senami 	psc->sc_io_window = -1;
335c66b8643Sthorpej }
336c66b8643Sthorpej 
337c66b8643Sthorpej int
ep_pcmcia_detach(device_t self,int flags)33891ca465cSchristos ep_pcmcia_detach(device_t self, int flags)
339d0889022Sthorpej {
34091ca465cSchristos 	struct ep_pcmcia_softc *psc = device_private(self);
341ea45df4dSaugustss 	int rv;
342ea45df4dSaugustss 
343c7573d51Senami 	if (psc->sc_io_window == -1)
344c7573d51Senami 		/* Nothing to detach. */
34591ca465cSchristos 		return 0;
346c7573d51Senami 
347ea45df4dSaugustss 	rv = ep_detach(self, flags);
348c7573d51Senami 	if (rv != 0)
34991ca465cSchristos 		return rv;
350d0889022Sthorpej 
351257d3e31Sthorpej 	/* Unmap our i/o window. */
352257d3e31Sthorpej 	pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
353257d3e31Sthorpej 
354257d3e31Sthorpej 	/* Free our i/o space. */
355257d3e31Sthorpej 	pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
356257d3e31Sthorpej 
35791ca465cSchristos 	return 0;
358d0889022Sthorpej }
359d0889022Sthorpej 
360d0889022Sthorpej int
ep_pcmcia_get_enaddr(struct pcmcia_tuple * tuple,void * arg)36191ca465cSchristos ep_pcmcia_get_enaddr(struct pcmcia_tuple *tuple, void *arg)
362c66b8643Sthorpej {
363c66b8643Sthorpej 	u_int8_t *myla = arg;
364c66b8643Sthorpej 	int i;
365c66b8643Sthorpej 
366441bea91Schristos 	/* this is 3c562a-c magic */
367c66b8643Sthorpej 	if (tuple->code == 0x88) {
368c66b8643Sthorpej 		if (tuple->length < ETHER_ADDR_LEN)
36991ca465cSchristos 			return 0;
370c66b8643Sthorpej 
371c66b8643Sthorpej 		for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
372c66b8643Sthorpej 			myla[i] = pcmcia_tuple_read_1(tuple, i + 1);
373c66b8643Sthorpej 			myla[i + 1] = pcmcia_tuple_read_1(tuple, i);
374c66b8643Sthorpej 		}
375c66b8643Sthorpej 
37691ca465cSchristos 		return 1;
377c66b8643Sthorpej 	}
37891ca465cSchristos 	return 0;
379c66b8643Sthorpej }
380