Annotation of sys/dev/pcmcia/if_ep_pcmcia.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_ep_pcmcia.c,v 1.36 2007/05/08 20:25:17 deraadt Exp $ */
2: /* $NetBSD: if_ep_pcmcia.c,v 1.16 1998/08/17 23:20:40 thorpej Exp $ */
3:
4: /*-
5: * Copyright (c) 1998 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10: * NASA Ames Research Center.
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: * 3. All advertising materials mentioning features or use of this software
21: * must display the following acknowledgement:
22: * This product includes software developed by the NetBSD
23: * Foundation, Inc. and its contributors.
24: * 4. Neither the name of The NetBSD Foundation nor the names of its
25: * contributors may be used to endorse or promote products derived
26: * from this software without specific prior written permission.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38: * POSSIBILITY OF SUCH DAMAGE.
39: */
40:
41: /*
42: * Copyright (c) 1997 Marc Horowitz. All rights reserved.
43: *
44: * Redistribution and use in source and binary forms, with or without
45: * modification, are permitted provided that the following conditions
46: * are met:
47: * 1. Redistributions of source code must retain the above copyright
48: * notice, this list of conditions and the following disclaimer.
49: * 2. Redistributions in binary form must reproduce the above copyright
50: * notice, this list of conditions and the following disclaimer in the
51: * documentation and/or other materials provided with the distribution.
52: * 3. All advertising materials mentioning features or use of this software
53: * must display the following acknowledgement:
54: * This product includes software developed by Marc Horowitz.
55: * 4. The name of the author may not be used to endorse or promote products
56: * derived from this software without specific prior written permission.
57: *
58: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
59: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
60: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
61: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
62: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
63: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
64: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
65: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
67: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68: */
69:
70: #include "bpfilter.h"
71:
72: #include <sys/param.h>
73: #include <sys/systm.h>
74: #include <sys/mbuf.h>
75: #include <sys/socket.h>
76: #include <sys/ioctl.h>
77: #include <sys/errno.h>
78: #include <sys/syslog.h>
79: #include <sys/selinfo.h>
80: #include <sys/timeout.h>
81: #include <sys/device.h>
82:
83: #include <net/if.h>
84: #include <net/if_dl.h>
85: #include <net/if_types.h>
86: #include <net/netisr.h>
87: #include <net/if_media.h>
88:
89: #ifdef INET
90: #include <netinet/in.h>
91: #include <netinet/in_systm.h>
92: #include <netinet/in_var.h>
93: #include <netinet/ip.h>
94: #include <netinet/if_ether.h>
95: #endif
96:
97: #if NBPFILTER > 0
98: #include <net/bpf.h>
99: #endif
100:
101: #include <machine/cpu.h>
102: #include <machine/bus.h>
103:
104: #include <dev/mii/mii.h>
105: #include <dev/mii/miivar.h>
106:
107: #include <dev/ic/elink3var.h>
108: #include <dev/ic/elink3reg.h>
109:
110: #include <dev/pcmcia/pcmciareg.h>
111: #include <dev/pcmcia/pcmciavar.h>
112: #include <dev/pcmcia/pcmciadevs.h>
113:
114: int ep_pcmcia_match(struct device *, void *, void *);
115: void ep_pcmcia_attach(struct device *, struct device *, void *);
116: int ep_pcmcia_detach(struct device *, int);
117: int ep_pcmcia_activate(struct device *, enum devact);
118:
119: int ep_pcmcia_get_enaddr(struct pcmcia_tuple *, void *);
120: #ifdef notyet
121: int ep_pcmcia_enable(struct ep_softc *);
122: void ep_pcmcia_disable(struct ep_softc *);
123: void ep_pcmcia_disable1(struct ep_softc *);
124: #endif
125:
126: int ep_pcmcia_enable1(struct ep_softc *);
127:
128: struct ep_pcmcia_softc {
129: struct ep_softc sc_ep; /* real "ep" softc */
130:
131: /* PCMCIA-specific goo */
132: struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
133: int sc_io_window; /* our i/o window */
134: struct pcmcia_function *sc_pf; /* our PCMCIA function */
135: };
136:
137: struct cfattach ep_pcmcia_ca = {
138: sizeof(struct ep_pcmcia_softc), ep_pcmcia_match, ep_pcmcia_attach,
139: ep_pcmcia_detach, ep_pcmcia_activate
140: };
141:
142: struct ep_pcmcia_product {
143: u_int16_t epp_product; /* PCMCIA product ID */
144: u_short epp_chipset; /* 3Com chipset used */
145: int epp_flags; /* initial softc flags */
146: int epp_expfunc; /* expected function */
147: } ep_pcmcia_prod[] = {
148: { PCMCIA_PRODUCT_3COM_3C562, EP_CHIPSET_3C509,
149: 0, 0 },
150:
151: { PCMCIA_PRODUCT_3COM_3C589, EP_CHIPSET_3C509,
152: 0, 0 },
153:
154: { PCMCIA_PRODUCT_3COM_3CXEM556, EP_CHIPSET_3C509,
155: 0, 0 },
156:
157: { PCMCIA_PRODUCT_3COM_3CXEM556B,EP_CHIPSET_3C509,
158: 0, 0 },
159:
160: { PCMCIA_PRODUCT_3COM_3C1, EP_CHIPSET_3C509,
161: 0, 0 },
162:
163: { PCMCIA_PRODUCT_3COM_3CCFEM556BI, EP_CHIPSET_ROADRUNNER,
164: EP_FLAGS_MII, 0 },
165:
166: { PCMCIA_PRODUCT_3COM_3C574, EP_CHIPSET_ROADRUNNER,
167: EP_FLAGS_MII, 0 }
168: };
169:
170: struct ep_pcmcia_product *ep_pcmcia_lookup(struct pcmcia_attach_args *);
171:
172: struct ep_pcmcia_product *
173: ep_pcmcia_lookup(pa)
174: struct pcmcia_attach_args *pa;
175: {
176: int i;
177:
178: for (i = 0; i < sizeof(ep_pcmcia_prod)/sizeof(ep_pcmcia_prod[0]); i++)
179: if (pa->product == ep_pcmcia_prod[i].epp_product &&
180: pa->pf->number == ep_pcmcia_prod[i].epp_expfunc)
181: return &ep_pcmcia_prod[i];
182:
183: return (NULL);
184: }
185:
186: int
187: ep_pcmcia_match(parent, match, aux)
188: struct device *parent;
189: void *match, *aux;
190: {
191: struct pcmcia_attach_args *pa = aux;
192:
193: if (pa->manufacturer != PCMCIA_VENDOR_3COM)
194: return (0);
195:
196: if (ep_pcmcia_lookup(pa) != NULL)
197: return (1);
198:
199: return (0);
200: }
201:
202: #ifdef notdef
203: int
204: ep_pcmcia_enable(sc)
205: struct ep_softc *sc;
206: {
207: struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
208: struct pcmcia_function *pf = psc->sc_pf;
209:
210: /* establish the interrupt. */
211: sc->sc_ih = pcmcia_intr_establish(pf, IPL_NET, epintr,
212: sc, sc->sc_dev.dv_xname);
213: if (sc->sc_ih == NULL) {
214: printf("%s: couldn't establish interrupt\n",
215: sc->sc_dev.dv_xname);
216: return (1);
217: }
218:
219: return (ep_pcmcia_enable1(sc));
220: }
221: #endif
222:
223: int
224: ep_pcmcia_enable1(sc)
225: struct ep_softc *sc;
226: {
227: struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
228: struct pcmcia_function *pf = psc->sc_pf;
229: int ret;
230:
231: if ((ret = pcmcia_function_enable(pf)))
232: return (ret);
233:
234: if ((psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3C562) ||
235: (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556) ||
236: (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556B)) {
237: int reg;
238:
239: /* turn off the serial-disable bit */
240:
241: reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
242: if (reg & 0x08) {
243: reg &= ~0x08;
244: pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
245: }
246:
247: }
248:
249: return (ret);
250: }
251:
252: #ifdef notyet
253: void
254: ep_pcmcia_disable(sc)
255: struct ep_softc *sc;
256: {
257: struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
258:
259: pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih);
260: ep_pcmcia_disable1(sc);
261: }
262:
263: void
264: ep_pcmcia_disable1(sc)
265: struct ep_softc *sc;
266: {
267: struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *) sc;
268:
269: pcmcia_function_disable(psc->sc_pf);
270: }
271: #endif
272:
273: void
274: ep_pcmcia_attach(parent, self, aux)
275: struct device *parent, *self;
276: void *aux;
277: {
278: struct ep_pcmcia_softc *psc = (void *) self;
279: struct ep_softc *sc = &psc->sc_ep;
280: struct pcmcia_attach_args *pa = aux;
281: struct pcmcia_config_entry *cfe;
282: struct ep_pcmcia_product *epp;
283: u_int8_t myla[ETHER_ADDR_LEN];
284: u_int8_t *enaddr = NULL;
285: const char *intrstr;
286: int i;
287:
288: psc->sc_pf = pa->pf;
289: cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head);
290:
291: /* Enable the card. */
292: pcmcia_function_init(pa->pf, cfe);
293: if (ep_pcmcia_enable1(sc))
294: printf(": function enable failed\n");
295:
296: #ifdef notyet
297: sc->enabled = 1;
298: #endif
299:
300: if (cfe->num_memspace != 0)
301: printf(": unexpected number of memory spaces %d should be 0\n",
302: cfe->num_memspace);
303:
304: if (cfe->num_iospace != 1)
305: printf(": unexpected number of I/O spaces %d should be 1\n",
306: cfe->num_iospace);
307:
308: if (pa->product == PCMCIA_PRODUCT_3COM_3C562) {
309: bus_addr_t maxaddr = (pa->pf->sc->iobase + pa->pf->sc->iosize);
310:
311: for (i = pa->pf->sc->iobase; i < maxaddr; i += 0x10) {
312: /*
313: * the 3c562 can only use 0x??00-0x??7f
314: * according to the Linux driver
315: */
316: if (i & 0x80)
317: continue;
318: if (pcmcia_io_alloc(pa->pf, i, cfe->iospace[0].length,
319: cfe->iospace[0].length, &psc->sc_pcioh) == 0)
320: break;
321: }
322: if (i >= maxaddr) {
323: printf(": can't allocate i/o space\n");
324: return;
325: }
326: } else {
327: if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
328: cfe->iospace[0].length, &psc->sc_pcioh))
329: printf(": can't allocate i/o space\n");
330: }
331:
332: sc->sc_iot = psc->sc_pcioh.iot;
333: sc->sc_ioh = psc->sc_pcioh.ioh;
334:
335: if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
336: PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, cfe->iospace[0].length,
337: &psc->sc_pcioh, &psc->sc_io_window)) {
338: printf(": can't map i/o space\n");
339: return;
340: }
341:
342: printf(" port 0x%lx/%d", psc->sc_pcioh.addr, psc->sc_pcioh.size);
343:
344: switch (pa->product) {
345: case PCMCIA_PRODUCT_3COM_3C562:
346: /*
347: * 3c562a-c use this; 3c562d does it in the regular way.
348: * we might want to check the revision and produce a warning
349: * in the future.
350: */
351: /* FALLTHROUGH */
352: case PCMCIA_PRODUCT_3COM_3C574:
353: case PCMCIA_PRODUCT_3COM_3CCFEM556BI:
354: /*
355: * Apparently, some 3c574s do it this way, as well.
356: */
357: if (pcmcia_scan_cis(parent, ep_pcmcia_get_enaddr, myla))
358: enaddr = myla;
359: break;
360: }
361:
362: sc->bustype = EP_BUS_PCMCIA;
363:
364: epp = ep_pcmcia_lookup(pa);
365: if (epp == NULL)
366: panic("ep_pcmcia_attach: impossible");
367:
368: sc->ep_flags = epp->epp_flags;
369:
370: #ifdef notyet
371: sc->enable = ep_pcmcia_enable;
372: sc->disable = ep_pcmcia_disable;
373: #endif
374:
375: /* establish the interrupt. */
376: sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, epintr, sc,
377: sc->sc_dev.dv_xname);
378: intrstr = pcmcia_intr_string(psc->sc_pf, sc->sc_ih);
379: if (*intrstr)
380: printf(", %s", intrstr);
381:
382: printf(":");
383:
384: epconfig(sc, epp->epp_chipset, enaddr);
385:
386: #ifdef notyet
387: sc->enabled = 0;
388:
389: ep_pcmcia_disable1(sc);
390: #endif
391: }
392:
393: int
394: ep_pcmcia_detach(dev, flags)
395: struct device *dev;
396: int flags;
397: {
398: int rv;
399: struct ep_pcmcia_softc *psc = (struct ep_pcmcia_softc *)dev;
400:
401: if ((rv = ep_detach(dev)) != 0)
402: return (rv);
403:
404: pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
405: pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
406:
407: return (0);
408: }
409:
410: int
411: ep_pcmcia_activate(dev, act)
412: struct device *dev;
413: enum devact act;
414: {
415: struct ep_pcmcia_softc *sc = (struct ep_pcmcia_softc *)dev;
416: struct ep_softc *esc = &sc->sc_ep;
417: struct ifnet *ifp = &esc->sc_arpcom.ac_if;
418: int s;
419:
420: s = splnet();
421: switch (act) {
422: case DVACT_ACTIVATE:
423: pcmcia_function_enable(sc->sc_pf);
424: sc->sc_ep.sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET,
425: epintr, sc, esc->sc_dev.dv_xname);
426: epinit(esc);
427: break;
428:
429: case DVACT_DEACTIVATE:
430: ifp->if_timer = 0;
431: if (ifp->if_flags & IFF_RUNNING)
432: epstop(esc);
433: pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ep.sc_ih);
434: pcmcia_function_disable(sc->sc_pf);
435: break;
436: }
437: splx(s);
438: return (0);
439: }
440:
441: int
442: ep_pcmcia_get_enaddr(tuple, arg)
443: struct pcmcia_tuple *tuple;
444: void *arg;
445: {
446: u_int8_t *myla = arg;
447: int i;
448:
449: /* this is 3c562a-c magic */
450: if (tuple->code == 0x88) {
451: if (tuple->length < ETHER_ADDR_LEN)
452: return (0);
453:
454: for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
455: myla[i] = pcmcia_tuple_read_1(tuple, i + 1);
456: myla[i + 1] = pcmcia_tuple_read_1(tuple, i);
457: }
458:
459: return (1);
460: }
461: return (0);
462: }
CVSweb