Annotation of sys/dev/pcmcia/if_xe.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_xe.c,v 1.33 2007/06/06 09:43:44 henning Exp $ */
2:
3: /*
4: * Copyright (c) 1999 Niklas Hallqvist, Brandon Creighton, Job de Haas
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Niklas Hallqvist,
18: * C Stone and Job de Haas.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
34: /*
35: * A driver for Xircom ethernet PC-cards.
36: *
37: * The driver has been inspired by the xirc2ps_cs.c driver found in Linux'
38: * PCMCIA package written by Werner Koch <werner.koch@guug.de>:
39: * [xirc2ps_cs.c wk 14.04.97] (1.31 1998/12/09 19:32:55)
40: * I will note that no code was used verbatim from that driver as it is under
41: * the much too strong GNU General Public License, it was only used as a
42: * "specification" of sorts.
43: * Other inspirations have been if_fxp.c, if_ep_pcmcia.c and elink3.c as
44: * they were found in OpenBSD 2.4.
45: */
46:
47: #include "bpfilter.h"
48:
49: #include <sys/param.h>
50: #include <sys/systm.h>
51: #include <sys/device.h>
52: #include <sys/ioctl.h>
53: #include <sys/mbuf.h>
54: #include <sys/malloc.h>
55: #include <sys/kernel.h>
56: #include <sys/socket.h>
57: #include <sys/syslog.h>
58:
59: #include <net/if.h>
60: #include <net/if_dl.h>
61: #include <net/if_media.h>
62: #include <net/if_types.h>
63:
64: #ifdef INET
65: #include <netinet/in.h>
66: #include <netinet/in_systm.h>
67: #include <netinet/in_var.h>
68: #include <netinet/ip.h>
69: #include <netinet/if_ether.h>
70: #endif
71:
72: #if NBPFILTER > 0
73: #include <net/bpf.h>
74: #endif
75:
76: /*
77: * Maximum number of bytes to read per interrupt. Linux recommends
78: * somewhere between 2000-22000.
79: * XXX This is currently a hard maximum.
80: */
81: #define MAX_BYTES_INTR 12000
82:
83: #include <dev/mii/miivar.h>
84:
85: #include <dev/pcmcia/pcmciareg.h>
86: #include <dev/pcmcia/pcmciavar.h>
87: #include <dev/pcmcia/pcmciadevs.h>
88: #include <dev/pcmcia/if_xereg.h>
89:
90: #ifdef __GNUC__
91: #define INLINE __inline
92: #else
93: #define INLINE
94: #endif /* __GNUC__ */
95:
96: #ifdef XEDEBUG
97:
98: #define XED_CONFIG 0x1
99: #define XED_MII 0x2
100: #define XED_INTR 0x4
101: #define XED_FIFO 0x8
102:
103: #ifndef XEDEBUG_DEF
104: #define XEDEBUG_DEF (XED_CONFIG|XED_INTR)
105: #endif /* XEDEBUG_DEF */
106:
107: int xedebug = XEDEBUG_DEF;
108:
109: #define DPRINTF(cat, x) if (xedebug & (cat)) printf x
110:
111: #else /* XEDEBUG */
112: #define DPRINTF(cat, x) (void)0
113: #endif /* XEDEBUG */
114:
115: int xe_pcmcia_match(struct device *, void *, void *);
116: void xe_pcmcia_attach(struct device *, struct device *, void *);
117: int xe_pcmcia_detach(struct device *, int);
118: int xe_pcmcia_activate(struct device *, enum devact);
119:
120: /*
121: * In case this chipset ever turns up out of pcmcia attachments (very
122: * unlikely) do the driver splitup.
123: */
124: struct xe_softc {
125: struct device sc_dev; /* Generic device info */
126: u_int32_t sc_flags; /* Misc. flags */
127: void *sc_ih; /* Interrupt handler */
128: struct arpcom sc_arpcom; /* Ethernet common part */
129: struct ifmedia sc_media; /* Media control */
130: struct mii_data sc_mii; /* MII media information */
131: int sc_all_mcasts; /* Receive all multicasts */
132: bus_space_tag_t sc_bst; /* Bus cookie */
133: bus_space_handle_t sc_bsh; /* Bus I/O handle */
134: bus_size_t sc_offset; /* Offset of registers */
135: u_int8_t sc_rev; /* Chip revision */
136: };
137:
138: #define XEF_MOHAWK 0x001
139: #define XEF_DINGO 0x002
140: #define XEF_MODEM 0x004
141: #define XEF_UNSUPPORTED 0x008
142: #define XEF_CE 0x010
143: #define XEF_CE2 0x020
144: #define XEF_CE3 0x040
145: #define XEF_CE33 0x080
146: #define XEF_CE56 0x100
147:
148: struct xe_pcmcia_softc {
149: struct xe_softc sc_xe; /* Generic device info */
150: struct pcmcia_mem_handle sc_pcmh; /* PCMCIA memspace info */
151: int sc_mem_window; /* mem window */
152: struct pcmcia_io_handle sc_pcioh; /* iospace info */
153: int sc_io_window; /* io window info */
154: struct pcmcia_function *sc_pf; /* PCMCIA function */
155: };
156:
157: /* Autoconfig definition of driver back-end */
158: struct cfdriver xe_cd = {
159: NULL, "xe", DV_IFNET
160: };
161:
162: struct cfattach xe_pcmcia_ca = {
163: sizeof (struct xe_pcmcia_softc), xe_pcmcia_match, xe_pcmcia_attach,
164: xe_pcmcia_detach, xe_pcmcia_activate
165: };
166:
167: void xe_cycle_power(struct xe_softc *);
168: int xe_ether_ioctl(struct ifnet *, u_long cmd, caddr_t);
169: void xe_full_reset(struct xe_softc *);
170: void xe_init(struct xe_softc *);
171: int xe_intr(void *);
172: int xe_ioctl(struct ifnet *, u_long, caddr_t);
173: int xe_mdi_read(struct device *, int, int);
174: void xe_mdi_write(struct device *, int, int, int);
175: int xe_mediachange(struct ifnet *);
176: void xe_mediastatus(struct ifnet *, struct ifmediareq *);
177: int xe_pcmcia_funce_enaddr(struct device *, u_int8_t *);
178: u_int32_t xe_pcmcia_interpret_manfid(struct device *);
179: int xe_pcmcia_lan_nid_ciscallback(struct pcmcia_tuple *, void *);
180: int xe_pcmcia_manfid_ciscallback(struct pcmcia_tuple *, void *);
181: u_int16_t xe_get(struct xe_softc *);
182: void xe_reset(struct xe_softc *);
183: void xe_set_address(struct xe_softc *);
184: void xe_start(struct ifnet *);
185: void xe_statchg(struct device *);
186: void xe_stop(struct xe_softc *);
187: void xe_watchdog(struct ifnet *);
188: #ifdef XEDEBUG
189: void xe_reg_dump(struct xe_softc *);
190: #endif /* XEDEBUG */
191:
192: int
193: xe_pcmcia_match(parent, match, aux)
194: struct device *parent;
195: void *match, *aux;
196: {
197: struct pcmcia_attach_args *pa = aux;
198:
199: if (pa->pf->function != PCMCIA_FUNCTION_NETWORK)
200: return (0);
201:
202: switch (pa->manufacturer) {
203: case PCMCIA_VENDOR_COMPAQ:
204: case PCMCIA_VENDOR_COMPAQ2:
205: return (0);
206:
207: case PCMCIA_VENDOR_INTEL:
208: case PCMCIA_VENDOR_XIRCOM:
209: /* XXX Per-productid checking here. */
210: return (1);
211:
212: default:
213: return (0);
214: }
215: }
216:
217: void
218: xe_pcmcia_attach(parent, self, aux)
219: struct device *parent, *self;
220: void *aux;
221: {
222: struct xe_pcmcia_softc *psc = (struct xe_pcmcia_softc *)self;
223: struct xe_softc *sc = &psc->sc_xe;
224: struct pcmcia_attach_args *pa = aux;
225: struct pcmcia_function *pf = pa->pf;
226: struct pcmcia_config_entry *cfe;
227: struct ifnet *ifp;
228: u_int8_t myla[ETHER_ADDR_LEN], *enaddr = NULL;
229: int state = 0;
230: struct pcmcia_mem_handle pcmh;
231: int ccr_window;
232: bus_size_t ccr_offset;
233: const char *intrstr;
234:
235: psc->sc_pf = pf;
236:
237: #if 0
238: /* Figure out what card we are. */
239: sc->sc_flags = xe_pcmcia_interpret_manfid(parent);
240: #endif
241: if (sc->sc_flags & XEF_UNSUPPORTED) {
242: printf(": card unsupported\n");
243: goto bad;
244: }
245:
246: /* Tell the pcmcia framework where the CCR is. */
247: pf->ccr_base = 0x800;
248: pf->ccr_mask = 0x67;
249:
250: /* Fake a cfe. */
251: SIMPLEQ_FIRST(&pa->pf->cfe_head) = cfe = (struct pcmcia_config_entry *)
252: malloc(sizeof *cfe, M_DEVBUF, M_NOWAIT);
253: if (!cfe) {
254: printf(": function enable failed\n");
255: return;
256: }
257: bzero(cfe, sizeof *cfe);
258:
259: /*
260: * XXX Use preprocessor symbols instead.
261: * Enable ethernet & its interrupts, wiring them to -INT
262: * No I/O base.
263: */
264: cfe->number = 0x5;
265: cfe->flags = 0; /* XXX Check! */
266: cfe->iftype = PCMCIA_IFTYPE_IO;
267: cfe->num_iospace = 0;
268: cfe->num_memspace = 0;
269: cfe->irqmask = 0x8eb0;
270:
271: /* Enable the card. */
272: pcmcia_function_init(pa->pf, cfe);
273: if (pcmcia_function_enable(pa->pf)) {
274: printf(": function enable failed\n");
275: goto bad;
276: }
277:
278: state++;
279:
280: if (pcmcia_io_alloc(pa->pf, 0, 16, 16, &psc->sc_pcioh)) {
281: printf(": io allocation failed\n");
282: goto bad;
283: }
284:
285: state++;
286:
287: if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_IO16, 0, 16, &psc->sc_pcioh,
288: &psc->sc_io_window)) {
289: printf(": can't map io space\n");
290: goto bad;
291: }
292: sc->sc_bst = psc->sc_pcioh.iot;
293: sc->sc_bsh = psc->sc_pcioh.ioh;
294: sc->sc_offset = 0;
295:
296: printf(" port 0x%lx/%d", psc->sc_pcioh.addr, 16);
297:
298: #if 0
299: if (pcmcia_mem_alloc(pf, 16, &psc->sc_pcmh)) {
300: printf(": pcmcia memory allocation failed\n");
301: goto bad;
302: }
303: state++;
304:
305: if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, 0x300, 16, &psc->sc_pcmh,
306: &sc->sc_offset, &psc->sc_mem_window)) {
307: printf(": pcmcia memory mapping failed\n");
308: goto bad;
309: }
310:
311: sc->sc_bst = psc->sc_pcmh.memt;
312: sc->sc_bsh = psc->sc_pcmh.memh;
313: #endif
314:
315: /* Figure out what card we are. */
316: sc->sc_flags = xe_pcmcia_interpret_manfid(parent);
317:
318: /*
319: * Configuration as advised by DINGO documentation.
320: * We only know about this flag after the manfid interpretation.
321: * Dingo has some extra configuration registers in the CCR space.
322: */
323: if (sc->sc_flags & XEF_DINGO) {
324: if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE_DINGO, &pcmh)) {
325: DPRINTF(XED_CONFIG, ("bad mem alloc\n"));
326: goto bad;
327: }
328:
329: if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
330: PCMCIA_CCR_SIZE_DINGO, &pcmh, &ccr_offset,
331: &ccr_window)) {
332: DPRINTF(XED_CONFIG, ("bad mem map\n"));
333: pcmcia_mem_free(pf, &pcmh);
334: goto bad;
335: }
336:
337: bus_space_write_1(pcmh.memt, pcmh.memh,
338: ccr_offset + PCMCIA_CCR_DCOR0, PCMCIA_CCR_DCOR0_SFINT);
339: bus_space_write_1(pcmh.memt, pcmh.memh,
340: ccr_offset + PCMCIA_CCR_DCOR1,
341: PCMCIA_CCR_DCOR1_FORCE_LEVIREQ | PCMCIA_CCR_DCOR1_D6);
342: bus_space_write_1(pcmh.memt, pcmh.memh,
343: ccr_offset + PCMCIA_CCR_DCOR2, 0);
344: bus_space_write_1(pcmh.memt, pcmh.memh,
345: ccr_offset + PCMCIA_CCR_DCOR3, 0);
346: bus_space_write_1(pcmh.memt, pcmh.memh,
347: ccr_offset + PCMCIA_CCR_DCOR4, 0);
348:
349: /* We don't need them anymore and can free them (I think). */
350: pcmcia_mem_unmap(pf, ccr_window);
351: pcmcia_mem_free(pf, &pcmh);
352: }
353:
354: /*
355: * Try to get the ethernet address from FUNCE/LAN_NID tuple.
356: */
357: if (xe_pcmcia_funce_enaddr(parent, myla))
358: enaddr = myla;
359: ifp = &sc->sc_arpcom.ac_if;
360: if (enaddr)
361: bcopy(enaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
362: else {
363: printf(", unable to get ethernet address\n");
364: goto bad;
365: }
366:
367: bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
368: ifp->if_softc = sc;
369: ifp->if_flags =
370: IFF_BROADCAST | IFF_NOTRAILERS | IFF_SIMPLEX | IFF_MULTICAST;
371: ifp->if_ioctl = xe_ioctl;
372: ifp->if_start = xe_start;
373: ifp->if_watchdog = xe_watchdog;
374: IFQ_SET_READY(&ifp->if_snd);
375:
376: /* Establish the interrupt. */
377: sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, xe_intr, sc,
378: sc->sc_dev.dv_xname);
379: if (sc->sc_ih == NULL) {
380: printf(", couldn't establish interrupt\n");
381: goto bad;
382: }
383: intrstr = pcmcia_intr_string(psc->sc_pf, sc->sc_ih);
384: printf("%s%s: address %s\n", *intrstr ? ", " : "", intrstr,
385: ether_sprintf(sc->sc_arpcom.ac_enaddr));
386:
387: /* Reset and initialize the card. */
388: xe_full_reset(sc);
389:
390: /* Initialize our media structures and probe the phy. */
391: sc->sc_mii.mii_ifp = ifp;
392: sc->sc_mii.mii_readreg = xe_mdi_read;
393: sc->sc_mii.mii_writereg = xe_mdi_write;
394: sc->sc_mii.mii_statchg = xe_statchg;
395: ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, xe_mediachange,
396: xe_mediastatus);
397: DPRINTF(XED_MII | XED_CONFIG,
398: ("bmsr %x\n", xe_mdi_read(&sc->sc_dev, 0, 1)));
399: mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
400: 0);
401: if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL)
402: ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO, 0,
403: NULL);
404: ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO);
405:
406: /*
407: * Attach the interface.
408: */
409: if_attach(ifp);
410: ether_ifattach(ifp);
411:
412: /*
413: * Reset and initialize the card again for DINGO (as found in Linux
414: * driver). Without this Dingo will get a watchdog timeout the first
415: * time. The ugly media tickling seems to be necessary for getting
416: * autonegotiation to work too.
417: */
418: if (sc->sc_flags & XEF_DINGO) {
419: xe_full_reset(sc);
420: xe_init(sc);
421: ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO);
422: ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_NONE);
423: xe_stop(sc);
424: }
425:
426: #ifdef notyet
427: pcmcia_function_disable(pa->pf);
428: #endif /* notyet */
429:
430: return;
431:
432: bad:
433: if (state > 2)
434: pcmcia_io_unmap(pf, psc->sc_io_window);
435: if (state > 1)
436: pcmcia_io_free(pf, &psc->sc_pcioh);
437: if (state > 0)
438: pcmcia_function_disable(pa->pf);
439: free(cfe, M_DEVBUF);
440: }
441:
442: int
443: xe_pcmcia_detach(dev, flags)
444: struct device *dev;
445: int flags;
446: {
447: struct xe_pcmcia_softc *psc = (struct xe_pcmcia_softc *)dev;
448: struct xe_softc *sc = &psc->sc_xe;
449: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
450: int rv = 0;
451:
452: mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
453: ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
454:
455: pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
456: pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
457:
458: ether_ifdetach(ifp);
459: if_detach(ifp);
460:
461: return (rv);
462: }
463:
464: int
465: xe_pcmcia_activate(dev, act)
466: struct device *dev;
467: enum devact act;
468: {
469: struct xe_pcmcia_softc *sc = (struct xe_pcmcia_softc *)dev;
470: struct ifnet *ifp = &sc->sc_xe.sc_arpcom.ac_if;
471: int s;
472:
473: s = splnet();
474: switch (act) {
475: case DVACT_ACTIVATE:
476: pcmcia_function_enable(sc->sc_pf);
477: sc->sc_xe.sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET,
478: xe_intr, sc, sc->sc_xe.sc_dev.dv_xname);
479: xe_init(&sc->sc_xe);
480: break;
481:
482: case DVACT_DEACTIVATE:
483: ifp->if_timer = 0;
484: if (ifp->if_flags & IFF_RUNNING)
485: xe_stop(&sc->sc_xe);
486: pcmcia_intr_disestablish(sc->sc_pf, sc->sc_xe.sc_ih);
487: pcmcia_function_disable(sc->sc_pf);
488: break;
489: }
490: splx(s);
491: return (0);
492: }
493:
494: /*
495: * XXX These two functions might be OK to factor out into pcmcia.c since
496: * if_sm_pcmcia.c uses similar ones.
497: */
498: int
499: xe_pcmcia_funce_enaddr(parent, myla)
500: struct device *parent;
501: u_int8_t *myla;
502: {
503: /* XXX The Linux driver has more ways to do this in case of failure. */
504: return (pcmcia_scan_cis(parent, xe_pcmcia_lan_nid_ciscallback, myla));
505: }
506:
507: int
508: xe_pcmcia_lan_nid_ciscallback(tuple, arg)
509: struct pcmcia_tuple *tuple;
510: void *arg;
511: {
512: u_int8_t *myla = arg;
513: int i;
514:
515: if (tuple->code == PCMCIA_CISTPL_FUNCE) {
516: if (tuple->length < 2)
517: return (0);
518:
519: switch (pcmcia_tuple_read_1(tuple, 0)) {
520: case PCMCIA_TPLFE_TYPE_LAN_NID:
521: if (pcmcia_tuple_read_1(tuple, 1) != ETHER_ADDR_LEN)
522: return (0);
523: break;
524:
525: case 0x02:
526: /*
527: * Not sure about this, I don't have a CE2
528: * that puts the ethernet addr here.
529: */
530: if (pcmcia_tuple_read_1(tuple, 1) != 13)
531: return (0);
532: break;
533:
534: default:
535: return (0);
536: }
537:
538: for (i = 0; i < ETHER_ADDR_LEN; i++)
539: myla[i] = pcmcia_tuple_read_1(tuple, i + 2);
540: return (1);
541: }
542:
543: /* Yet another spot where this might be. */
544: if (tuple->code == 0x89) {
545: pcmcia_tuple_read_1(tuple, 1);
546: for (i = 0; i < ETHER_ADDR_LEN; i++)
547: myla[i] = pcmcia_tuple_read_1(tuple, i + 2);
548: return (1);
549: }
550: return (0);
551: }
552:
553: u_int32_t
554: xe_pcmcia_interpret_manfid (parent)
555: struct device *parent;
556: {
557: u_int32_t flags = 0;
558: struct pcmcia_softc *psc = (struct pcmcia_softc *)parent;
559: char *tptr;
560:
561: if (!pcmcia_scan_cis(parent, xe_pcmcia_manfid_ciscallback, &flags))
562: return (XEF_UNSUPPORTED);
563:
564: if (flags & XEF_CE) {
565: tptr = memchr(psc->card.cis1_info[2], 'C',
566: strlen(psc->card.cis1_info[2]));
567: /* XXX not sure if other CE2s hide "CE2" in different places */
568: if (tptr && *(tptr + 1) == 'E' && *(tptr + 2) == '2') {
569: flags ^= (XEF_CE | XEF_UNSUPPORTED);
570: flags |= XEF_CE2;
571: }
572: }
573: return (flags);
574: }
575:
576: int
577: xe_pcmcia_manfid_ciscallback(tuple, arg)
578: struct pcmcia_tuple *tuple;
579: void *arg;
580: {
581: u_int32_t *flagsp = arg;
582: u_int8_t media, product;
583:
584: if (tuple->code == PCMCIA_CISTPL_MANFID) {
585: if (tuple->length < 2)
586: return (0);
587:
588: media = pcmcia_tuple_read_1(tuple, 3);
589: product = pcmcia_tuple_read_1(tuple, 4);
590:
591: if (!(product & XEPROD_CREDITCARD) ||
592: !(media & XEMEDIA_ETHER)) {
593: *flagsp |= XEF_UNSUPPORTED;
594: return (1);
595: }
596:
597: if (media & XEMEDIA_MODEM)
598: *flagsp |= XEF_MODEM;
599:
600: switch (product & XEPROD_IDMASK) {
601: case 1:
602: /* XXX Can be CE2 too (we double-check later). */
603: *flagsp |= XEF_CE | XEF_UNSUPPORTED;
604: break;
605: case 2:
606: *flagsp |= XEF_CE2;
607: break;
608: case 3:
609: if (!(*flagsp & XEF_MODEM))
610: *flagsp |= XEF_MOHAWK;
611: *flagsp |= XEF_CE3;
612: break;
613: case 4:
614: *flagsp |= XEF_CE33;
615: break;
616: case 5:
617: *flagsp |= XEF_CE56 | XEF_MOHAWK;
618: break;
619: case 6:
620: case 7:
621: *flagsp |= XEF_CE56 | XEF_MOHAWK | XEF_DINGO;
622: break;
623: default:
624: *flagsp |= XEF_UNSUPPORTED;
625: break;
626: }
627:
628: return (1);
629: }
630: return (0);
631: }
632:
633: int
634: xe_intr(arg)
635: void *arg;
636: {
637: struct xe_softc *sc = arg;
638: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
639: u_int8_t esr, rsr, isr, rx_status, savedpage;
640: u_int16_t tx_status, recvcount = 0, tempint;
641:
642: ifp->if_timer = 0; /* turn watchdog timer off */
643:
644: if (sc->sc_flags & XEF_MOHAWK) {
645: /* Disable interrupt (Linux does it). */
646: bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR,
647: 0);
648: }
649:
650: savedpage =
651: bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + PR);
652:
653: PAGE(sc, 0);
654: esr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + ESR);
655: isr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + ISR0);
656: rsr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + RSR);
657:
658: /* Check to see if card has been ejected. */
659: if (isr == 0xff) {
660: printf("%s: interrupt for dead card\n", sc->sc_dev.dv_xname);
661: goto end;
662: }
663:
664: PAGE(sc, 40);
665: rx_status =
666: bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + RXST0);
667: tx_status =
668: bus_space_read_2(sc->sc_bst, sc->sc_bsh, sc->sc_offset + TXST0);
669:
670: /*
671: * XXX Linux writes to RXST0 and TXST* here. My CE2 works just fine
672: * without it, and I can't see an obvious reason for it.
673: */
674:
675: PAGE(sc, 0);
676: while (esr & FULL_PKT_RCV) {
677: if (!(rsr & RSR_RX_OK))
678: break;
679:
680: /* Compare bytes read this interrupt to hard maximum. */
681: if (recvcount > MAX_BYTES_INTR) {
682: DPRINTF(XED_INTR,
683: ("%s: too many bytes this interrupt\n",
684: sc->sc_dev.dv_xname));
685: ifp->if_iqdrops++;
686: /* Drop packet. */
687: bus_space_write_2(sc->sc_bst, sc->sc_bsh,
688: sc->sc_offset + DO0, DO_SKIP_RX_PKT);
689: }
690: tempint = xe_get(sc);
691: recvcount += tempint;
692: ifp->if_ibytes += tempint;
693: esr = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
694: sc->sc_offset + ESR);
695: rsr = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
696: sc->sc_offset + RSR);
697: }
698:
699: /* Packet too long? */
700: if (rsr & RSR_TOO_LONG) {
701: ifp->if_ierrors++;
702: DPRINTF(XED_INTR,
703: ("%s: packet too long\n", sc->sc_dev.dv_xname));
704: }
705:
706: /* CRC error? */
707: if (rsr & RSR_CRCERR) {
708: ifp->if_ierrors++;
709: DPRINTF(XED_INTR,
710: ("%s: CRC error detected\n", sc->sc_dev.dv_xname));
711: }
712:
713: /* Alignment error? */
714: if (rsr & RSR_ALIGNERR) {
715: ifp->if_ierrors++;
716: DPRINTF(XED_INTR,
717: ("%s: alignment error detected\n", sc->sc_dev.dv_xname));
718: }
719:
720: /* Check for rx overrun. */
721: if (rx_status & RX_OVERRUN) {
722: bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR,
723: CLR_RX_OVERRUN);
724: DPRINTF(XED_INTR, ("overrun cleared\n"));
725: }
726:
727: /* Try to start more packets transmitting. */
728: if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
729: xe_start(ifp);
730:
731: /* Detected excessive collisions? */
732: if ((tx_status & EXCESSIVE_COLL) && ifp->if_opackets > 0) {
733: DPRINTF(XED_INTR,
734: ("%s: excessive collisions\n", sc->sc_dev.dv_xname));
735: bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR,
736: RESTART_TX);
737: ifp->if_oerrors++;
738: }
739:
740: if ((tx_status & TX_ABORT) && ifp->if_opackets > 0)
741: ifp->if_oerrors++;
742:
743: end:
744: /* Reenable interrupts. */
745: PAGE(sc, savedpage);
746: bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR,
747: ENABLE_INT);
748:
749: return (1);
750: }
751:
752: u_int16_t
753: xe_get(sc)
754: struct xe_softc *sc;
755: {
756: u_int8_t rsr;
757: struct mbuf *top, **mp, *m;
758: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
759: u_int16_t pktlen, len, recvcount = 0;
760: u_int8_t *data;
761:
762: PAGE(sc, 0);
763: rsr = bus_space_read_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + RSR);
764:
765: pktlen =
766: bus_space_read_2(sc->sc_bst, sc->sc_bsh, sc->sc_offset + RBC0) &
767: RBC_COUNT_MASK;
768: if (pktlen == 0) {
769: /*
770: * XXX At least one CE2 sets RBC0 == 0 occasionally, and only
771: * when MPE is set. It is not known why.
772: */
773: return (0);
774: }
775: recvcount += pktlen;
776:
777: MGETHDR(m, M_DONTWAIT, MT_DATA);
778: if (m == 0)
779: return (recvcount);
780: m->m_pkthdr.rcvif = ifp;
781: m->m_pkthdr.len = pktlen;
782: len = MHLEN;
783: top = 0;
784: mp = ⊤
785:
786: while (pktlen > 0) {
787: if (top) {
788: MGET(m, M_DONTWAIT, MT_DATA);
789: if (m == 0) {
790: m_freem(top);
791: return (recvcount);
792: }
793: len = MLEN;
794: }
795: if (pktlen >= MINCLSIZE) {
796: MCLGET(m, M_DONTWAIT);
797: if (!(m->m_flags & M_EXT)) {
798: m_freem(m);
799: m_freem(top);
800: return (recvcount);
801: }
802: len = MCLBYTES;
803: }
804: if (!top) {
805: caddr_t newdata = (caddr_t)ALIGN(m->m_data +
806: sizeof (struct ether_header)) -
807: sizeof (struct ether_header);
808: len -= newdata - m->m_data;
809: m->m_data = newdata;
810: }
811: len = min(pktlen, len);
812:
813: data = mtod(m, u_int8_t *);
814: if (len > 1) {
815: len &= ~1;
816: bus_space_read_raw_multi_2(sc->sc_bst, sc->sc_bsh,
817: sc->sc_offset + EDP, data, len);
818: } else
819: *data = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
820: sc->sc_offset + EDP);
821: m->m_len = len;
822: pktlen -= len;
823: *mp = m;
824: mp = &m->m_next;
825: }
826:
827: /* Skip Rx packet. */
828: bus_space_write_2(sc->sc_bst, sc->sc_bsh, sc->sc_offset + DO0,
829: DO_SKIP_RX_PKT);
830:
831: ifp->if_ipackets++;
832:
833: #if NBPFILTER > 0
834: if (ifp->if_bpf)
835: bpf_mtap(ifp->if_bpf, top, BPF_DIRECTION_IN);
836: #endif
837:
838: ether_input_mbuf(ifp, top);
839: return (recvcount);
840: }
841:
842:
843: /*
844: * Serial management for the MII.
845: * The DELAY's below stem from the fact that the maximum frequency
846: * acceptable on the MDC pin is 2.5 MHz and fast processors can easily
847: * go much faster than that.
848: */
849:
850: /* Let the MII serial management be idle for one period. */
851: static INLINE void xe_mdi_idle(struct xe_softc *);
852: static INLINE void
853: xe_mdi_idle(sc)
854: struct xe_softc *sc;
855: {
856: bus_space_tag_t bst = sc->sc_bst;
857: bus_space_handle_t bsh = sc->sc_bsh;
858: bus_size_t offset = sc->sc_offset;
859:
860: /* Drive MDC low... */
861: bus_space_write_1(bst, bsh, offset + GP2, MDC_LOW);
862: DELAY(1);
863:
864: /* and high again. */
865: bus_space_write_1(bst, bsh, offset + GP2, MDC_HIGH);
866: DELAY(1);
867: }
868:
869: /* Pulse out one bit of data. */
870: static INLINE void xe_mdi_pulse(struct xe_softc *, int);
871: static INLINE void
872: xe_mdi_pulse(sc, data)
873: struct xe_softc *sc;
874: int data;
875: {
876: bus_space_tag_t bst = sc->sc_bst;
877: bus_space_handle_t bsh = sc->sc_bsh;
878: bus_size_t offset = sc->sc_offset;
879: u_int8_t bit = data ? MDIO_HIGH : MDIO_LOW;
880:
881: /* First latch the data bit MDIO with clock bit MDC low...*/
882: bus_space_write_1(bst, bsh, offset + GP2, bit | MDC_LOW);
883: DELAY(1);
884:
885: /* then raise the clock again, preserving the data bit. */
886: bus_space_write_1(bst, bsh, offset + GP2, bit | MDC_HIGH);
887: DELAY(1);
888: }
889:
890: /* Probe one bit of data. */
891: static INLINE int xe_mdi_probe(struct xe_softc *sc);
892: static INLINE int
893: xe_mdi_probe(sc)
894: struct xe_softc *sc;
895: {
896: bus_space_tag_t bst = sc->sc_bst;
897: bus_space_handle_t bsh = sc->sc_bsh;
898: bus_size_t offset = sc->sc_offset;
899: u_int8_t x;
900:
901: /* Pull clock bit MDCK low... */
902: bus_space_write_1(bst, bsh, offset + GP2, MDC_LOW);
903: DELAY(1);
904:
905: /* Read data and drive clock high again. */
906: x = bus_space_read_1(bst, bsh, offset + GP2) & MDIO;
907: bus_space_write_1(bst, bsh, offset + GP2, MDC_HIGH);
908: DELAY(1);
909:
910: return (x);
911: }
912:
913: /* Pulse out a sequence of data bits. */
914: static INLINE void xe_mdi_pulse_bits(struct xe_softc *, u_int32_t, int);
915: static INLINE void
916: xe_mdi_pulse_bits(sc, data, len)
917: struct xe_softc *sc;
918: u_int32_t data;
919: int len;
920: {
921: u_int32_t mask;
922:
923: for (mask = 1 << (len - 1); mask; mask >>= 1)
924: xe_mdi_pulse(sc, data & mask);
925: }
926:
927: /* Read a PHY register. */
928: int
929: xe_mdi_read(self, phy, reg)
930: struct device *self;
931: int phy;
932: int reg;
933: {
934: struct xe_softc *sc = (struct xe_softc *)self;
935: int i;
936: u_int32_t mask;
937: u_int32_t data = 0;
938:
939: PAGE(sc, 2);
940: for (i = 0; i < 32; i++) /* Synchronize. */
941: xe_mdi_pulse(sc, 1);
942: xe_mdi_pulse_bits(sc, 0x06, 4); /* Start + Read opcode */
943: xe_mdi_pulse_bits(sc, phy, 5); /* PHY address */
944: xe_mdi_pulse_bits(sc, reg, 5); /* PHY register */
945: xe_mdi_idle(sc); /* Turn around. */
946: xe_mdi_probe(sc); /* Drop initial zero bit. */
947:
948: for (mask = 1 << 15; mask; mask >>= 1)
949: if (xe_mdi_probe(sc))
950: data |= mask;
951: xe_mdi_idle(sc);
952:
953: DPRINTF(XED_MII,
954: ("xe_mdi_read: phy %d reg %d -> %x\n", phy, reg, data));
955: return (data);
956: }
957:
958: /* Write a PHY register. */
959: void
960: xe_mdi_write(self, phy, reg, value)
961: struct device *self;
962: int phy;
963: int reg;
964: int value;
965: {
966: struct xe_softc *sc = (struct xe_softc *)self;
967: int i;
968:
969: PAGE(sc, 2);
970: for (i = 0; i < 32; i++) /* Synchronize. */
971: xe_mdi_pulse(sc, 1);
972: xe_mdi_pulse_bits(sc, 0x05, 4); /* Start + Write opcode */
973: xe_mdi_pulse_bits(sc, phy, 5); /* PHY address */
974: xe_mdi_pulse_bits(sc, reg, 5); /* PHY register */
975: xe_mdi_pulse_bits(sc, 0x02, 2); /* Turn around. */
976: xe_mdi_pulse_bits(sc, value, 16); /* Write the data */
977: xe_mdi_idle(sc); /* Idle away. */
978:
979: DPRINTF(XED_MII,
980: ("xe_mdi_write: phy %d reg %d val %x\n", phy, reg, value));
981: }
982:
983: void
984: xe_statchg(self)
985: struct device *self;
986: {
987: /* XXX Update ifp->if_baudrate */
988: }
989:
990: /*
991: * Change media according to request.
992: */
993: int
994: xe_mediachange(ifp)
995: struct ifnet *ifp;
996: {
997: if (ifp->if_flags & IFF_UP)
998: xe_init(ifp->if_softc);
999: return (0);
1000: }
1001:
1002: /*
1003: * Notify the world which media we're using.
1004: */
1005: void
1006: xe_mediastatus(ifp, ifmr)
1007: struct ifnet *ifp;
1008: struct ifmediareq *ifmr;
1009: {
1010: struct xe_softc *sc = ifp->if_softc;
1011:
1012: mii_pollstat(&sc->sc_mii);
1013: ifmr->ifm_status = sc->sc_mii.mii_media_status;
1014: ifmr->ifm_active = sc->sc_mii.mii_media_active;
1015: }
1016:
1017: void
1018: xe_reset(sc)
1019: struct xe_softc *sc;
1020: {
1021: int s;
1022:
1023: s = splnet();
1024: xe_stop(sc);
1025: xe_full_reset(sc);
1026: xe_init(sc);
1027: splx(s);
1028: }
1029:
1030: void
1031: xe_watchdog(ifp)
1032: struct ifnet *ifp;
1033: {
1034: struct xe_softc *sc = ifp->if_softc;
1035:
1036: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
1037: ++sc->sc_arpcom.ac_if.if_oerrors;
1038:
1039: xe_reset(sc);
1040: }
1041:
1042: void
1043: xe_stop(sc)
1044: register struct xe_softc *sc;
1045: {
1046: /* Disable interrupts. */
1047: PAGE(sc, 0);
1048: bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + CR, 0);
1049:
1050: PAGE(sc, 1);
1051: bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + IMR0, 0);
1052:
1053: /* Power down, wait. */
1054: PAGE(sc, 4);
1055: bus_space_write_1(sc->sc_bst, sc->sc_bsh, sc->sc_offset + GP1, 0);
1056: DELAY(40000);
1057:
1058: /* Cancel watchdog timer. */
1059: sc->sc_arpcom.ac_if.if_timer = 0;
1060: }
1061:
1062: void
1063: xe_init(sc)
1064: struct xe_softc *sc;
1065: {
1066: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1067: int s;
1068:
1069: DPRINTF(XED_CONFIG, ("xe_init\n"));
1070:
1071: s = splnet();
1072:
1073: xe_set_address(sc);
1074:
1075: /* Set current media. */
1076: mii_mediachg(&sc->sc_mii);
1077:
1078: ifp->if_flags |= IFF_RUNNING;
1079: ifp->if_flags &= ~IFF_OACTIVE;
1080: splx(s);
1081: }
1082:
1083: /*
1084: * Start outputting on the interface.
1085: * Always called as splnet().
1086: */
1087: void
1088: xe_start(ifp)
1089: struct ifnet *ifp;
1090: {
1091: struct xe_softc *sc = ifp->if_softc;
1092: bus_space_tag_t bst = sc->sc_bst;
1093: bus_space_handle_t bsh = sc->sc_bsh;
1094: bus_size_t offset = sc->sc_offset;
1095: unsigned int s, len, pad = 0;
1096: struct mbuf *m0, *m;
1097: u_int16_t space;
1098:
1099: /* Don't transmit if interface is busy or not running. */
1100: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
1101: return;
1102:
1103: /* Peek at the next packet. */
1104: IFQ_POLL(&ifp->if_snd, m0);
1105: if (m0 == 0)
1106: return;
1107:
1108: /* We need to use m->m_pkthdr.len, so require the header. */
1109: if (!(m0->m_flags & M_PKTHDR))
1110: panic("xe_start: no header mbuf");
1111:
1112: len = m0->m_pkthdr.len;
1113:
1114: /* Pad to ETHER_MIN_LEN - ETHER_CRC_LEN. */
1115: if (len < ETHER_MIN_LEN - ETHER_CRC_LEN)
1116: pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
1117:
1118: PAGE(sc, 0);
1119: space = bus_space_read_2(bst, bsh, offset + TSO0) & 0x7fff;
1120: if (len + pad + 2 > space) {
1121: DPRINTF(XED_FIFO,
1122: ("%s: not enough space in output FIFO (%d > %d)\n",
1123: sc->sc_dev.dv_xname, len + pad + 2, space));
1124: return;
1125: }
1126:
1127: IFQ_DEQUEUE(&ifp->if_snd, m0);
1128:
1129: #if NBPFILTER > 0
1130: if (ifp->if_bpf)
1131: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
1132: #endif
1133:
1134: /*
1135: * Do the output at splhigh() so that an interrupt from another device
1136: * won't cause a FIFO underrun.
1137: */
1138: s = splhigh();
1139:
1140: bus_space_write_2(bst, bsh, offset + TSO2, (u_int16_t)len + pad + 2);
1141: bus_space_write_2(bst, bsh, offset + EDP, (u_int16_t)len + pad);
1142: for (m = m0; m; ) {
1143: if (m->m_len > 1)
1144: bus_space_write_raw_multi_2(bst, bsh, offset + EDP,
1145: mtod(m, u_int8_t *), m->m_len & ~1);
1146: if (m->m_len & 1)
1147: bus_space_write_1(bst, bsh, offset + EDP,
1148: *(mtod(m, u_int8_t *) + m->m_len - 1));
1149: MFREE(m, m0);
1150: m = m0;
1151: }
1152: if (sc->sc_flags & XEF_MOHAWK)
1153: bus_space_write_1(bst, bsh, offset + CR, TX_PKT | ENABLE_INT);
1154: else {
1155: for (; pad > 1; pad -= 2)
1156: bus_space_write_2(bst, bsh, offset + EDP, 0);
1157: if (pad == 1)
1158: bus_space_write_1(bst, bsh, offset + EDP, 0);
1159: }
1160:
1161: splx(s);
1162:
1163: ifp->if_timer = 5;
1164: ++ifp->if_opackets;
1165: }
1166:
1167: int
1168: xe_ether_ioctl(ifp, cmd, data)
1169: struct ifnet *ifp;
1170: u_long cmd;
1171: caddr_t data;
1172: {
1173: struct ifaddr *ifa = (struct ifaddr *)data;
1174: struct xe_softc *sc = ifp->if_softc;
1175:
1176: switch (cmd) {
1177: case SIOCSIFADDR:
1178: ifp->if_flags |= IFF_UP;
1179:
1180: switch (ifa->ifa_addr->sa_family) {
1181: #ifdef INET
1182: case AF_INET:
1183: xe_init(sc);
1184: arp_ifinit(&sc->sc_arpcom, ifa);
1185: break;
1186: #endif /* INET */
1187:
1188: default:
1189: xe_init(sc);
1190: break;
1191: }
1192: break;
1193:
1194: default:
1195: return (EINVAL);
1196: }
1197:
1198: return (0);
1199: }
1200:
1201: int
1202: xe_ioctl(ifp, command, data)
1203: struct ifnet *ifp;
1204: u_long command;
1205: caddr_t data;
1206: {
1207: struct xe_softc *sc = ifp->if_softc;
1208: struct ifreq *ifr = (struct ifreq *)data;
1209: int s, error = 0;
1210:
1211: s = splnet();
1212:
1213: switch (command) {
1214: case SIOCSIFADDR:
1215: error = xe_ether_ioctl(ifp, command, data);
1216: break;
1217:
1218: case SIOCSIFFLAGS:
1219: sc->sc_all_mcasts = (ifp->if_flags & IFF_ALLMULTI) ? 1 : 0;
1220:
1221: PAGE(sc, 0x42);
1222: if ((ifp->if_flags & IFF_PROMISC) ||
1223: (ifp->if_flags & IFF_ALLMULTI))
1224: bus_space_write_1(sc->sc_bst, sc->sc_bsh,
1225: sc->sc_offset + SWC1,
1226: SWC1_PROMISC | SWC1_MCAST_PROM);
1227: else
1228: bus_space_write_1(sc->sc_bst, sc->sc_bsh,
1229: sc->sc_offset + SWC1, 0);
1230:
1231: /*
1232: * If interface is marked up and not running, then start it.
1233: * If it is marked down and running, stop it.
1234: * XXX If it's up then re-initialize it. This is so flags
1235: * such as IFF_PROMISC are handled.
1236: */
1237: if (ifp->if_flags & IFF_UP) {
1238: xe_init(sc);
1239: } else {
1240: if (ifp->if_flags & IFF_RUNNING)
1241: xe_stop(sc);
1242: }
1243: break;
1244:
1245: case SIOCADDMULTI:
1246: case SIOCDELMULTI:
1247: sc->sc_all_mcasts = (ifp->if_flags & IFF_ALLMULTI) ? 1 : 0;
1248: error = (command == SIOCADDMULTI) ?
1249: ether_addmulti(ifr, &sc->sc_arpcom) :
1250: ether_delmulti(ifr, &sc->sc_arpcom);
1251:
1252: if (error == ENETRESET) {
1253: /*
1254: * Multicast list has changed; set the hardware
1255: * filter accordingly.
1256: */
1257: if (!sc->sc_all_mcasts &&
1258: !(ifp->if_flags & IFF_PROMISC))
1259: xe_set_address(sc);
1260:
1261: /*
1262: * xe_set_address() can turn on all_mcasts if we run
1263: * out of space, so check it again rather than else {}.
1264: */
1265: if (sc->sc_all_mcasts)
1266: xe_init(sc);
1267: error = 0;
1268: }
1269: break;
1270:
1271: case SIOCSIFMEDIA:
1272: case SIOCGIFMEDIA:
1273: error =
1274: ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
1275: break;
1276:
1277: default:
1278: error = EINVAL;
1279: }
1280: splx(s);
1281: return (error);
1282: }
1283:
1284: void
1285: xe_set_address(sc)
1286: struct xe_softc *sc;
1287: {
1288: bus_space_tag_t bst = sc->sc_bst;
1289: bus_space_handle_t bsh = sc->sc_bsh;
1290: bus_size_t offset = sc->sc_offset;
1291: struct arpcom *arp = &sc->sc_arpcom;
1292: struct ether_multi *enm;
1293: struct ether_multistep step;
1294: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1295: int i, page, pos, num;
1296:
1297: PAGE(sc, 0x50);
1298: for (i = 0; i < 6; i++) {
1299: bus_space_write_1(bst, bsh, offset + IA + i,
1300: sc->sc_arpcom.ac_enaddr[(sc->sc_flags & XEF_MOHAWK) ?
1301: 5 - i : i]);
1302: }
1303:
1304: if (arp->ac_multicnt > 0) {
1305: if (arp->ac_multicnt > 9) {
1306: PAGE(sc, 0x42);
1307: bus_space_write_1(sc->sc_bst, sc->sc_bsh,
1308: sc->sc_offset + SWC1,
1309: SWC1_PROMISC | SWC1_MCAST_PROM);
1310: return;
1311: }
1312:
1313: ETHER_FIRST_MULTI(step, arp, enm);
1314:
1315: pos = IA + 6;
1316: for (page = 0x50, num = arp->ac_multicnt; num > 0 && enm;
1317: num--) {
1318: if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
1319: sizeof(enm->enm_addrlo)) != 0) {
1320: /*
1321: * The multicast address is really a range;
1322: * it's easier just to accept all multicasts.
1323: * XXX should we be setting IFF_ALLMULTI here?
1324: */
1325: ifp->if_flags |= IFF_ALLMULTI;
1326: sc->sc_all_mcasts=1;
1327: break;
1328: }
1329:
1330: for (i = 0; i < 6; i++) {
1331: bus_space_write_1(bst, bsh, offset + pos,
1332: enm->enm_addrlo[
1333: (sc->sc_flags & XEF_MOHAWK) ? 5 - i : i]);
1334:
1335: if (++pos > 15) {
1336: pos = IA;
1337: page++;
1338: PAGE(sc, page);
1339: }
1340: }
1341: }
1342: }
1343: }
1344:
1345: void
1346: xe_cycle_power(sc)
1347: struct xe_softc *sc;
1348: {
1349: bus_space_tag_t bst = sc->sc_bst;
1350: bus_space_handle_t bsh = sc->sc_bsh;
1351: bus_size_t offset = sc->sc_offset;
1352:
1353: PAGE(sc, 4);
1354: DELAY(1);
1355: bus_space_write_1(bst, bsh, offset + GP1, 0);
1356: DELAY(40000);
1357: if (sc->sc_flags & XEF_MOHAWK)
1358: bus_space_write_1(bst, bsh, offset + GP1, POWER_UP);
1359: else
1360: /* XXX What is bit 2 (aka AIC)? */
1361: bus_space_write_1(bst, bsh, offset + GP1, POWER_UP | 4);
1362: DELAY(20000);
1363: }
1364:
1365: void
1366: xe_full_reset(sc)
1367: struct xe_softc *sc;
1368: {
1369: bus_space_tag_t bst = sc->sc_bst;
1370: bus_space_handle_t bsh = sc->sc_bsh;
1371: bus_size_t offset = sc->sc_offset;
1372:
1373: /* Do an as extensive reset as possible on all functions. */
1374: xe_cycle_power(sc);
1375: bus_space_write_1(bst, bsh, offset + CR, SOFT_RESET);
1376: DELAY(20000);
1377: bus_space_write_1(bst, bsh, offset + CR, 0);
1378: DELAY(20000);
1379: if (sc->sc_flags & XEF_MOHAWK) {
1380: PAGE(sc, 4);
1381: /*
1382: * Drive GP1 low to power up ML6692 and GP2 high to power up
1383: * the 10MHz chip. XXX What chip is that? The phy?
1384: */
1385: bus_space_write_1(bst, bsh, offset + GP0,
1386: GP1_OUT | GP2_OUT | GP2_WR);
1387: }
1388: DELAY(500000);
1389:
1390: /* Get revision information. XXX Symbolic constants. */
1391: sc->sc_rev = bus_space_read_1(bst, bsh, offset + BV) &
1392: ((sc->sc_flags & XEF_MOHAWK) ? 0x70 : 0x30) >> 4;
1393:
1394: /* Media selection. XXX Maybe manual overriding too? */
1395: if (!(sc->sc_flags & XEF_MOHAWK)) {
1396: PAGE(sc, 4);
1397: /*
1398: * XXX I have no idea what this really does, it is from the
1399: * Linux driver.
1400: */
1401: bus_space_write_1(bst, bsh, offset + GP0, GP1_OUT);
1402: }
1403: DELAY(40000);
1404:
1405: /* Setup the ethernet interrupt mask. */
1406: PAGE(sc, 1);
1407: bus_space_write_1(bst, bsh, offset + IMR0,
1408: ISR_TX_OFLOW | ISR_PKT_TX | ISR_MAC_INT | /* ISR_RX_EARLY | */
1409: ISR_RX_FULL | ISR_RX_PKT_REJ | ISR_FORCED_INT);
1410: #if 0
1411: bus_space_write_1(bst, bsh, offset + IMR0, 0xff);
1412: #endif
1413: if (!(sc->sc_flags & XEF_DINGO))
1414: /* XXX What is this? Not for Dingo at least. */
1415: bus_space_write_1(bst, bsh, offset + IMR1, 1);
1416:
1417: /*
1418: * Disable source insertion.
1419: * XXX Dingo does not have this bit, but Linux does it unconditionally.
1420: */
1421: if (!(sc->sc_flags & XEF_DINGO)) {
1422: PAGE(sc, 0x42);
1423: bus_space_write_1(bst, bsh, offset + SWC0, 0x20);
1424: }
1425:
1426: /* Set the local memory dividing line. */
1427: if (sc->sc_rev != 1) {
1428: PAGE(sc, 2);
1429: /* XXX Symbolic constant preferrable. */
1430: bus_space_write_2(bst, bsh, offset + RBS0, 0x2000);
1431: }
1432:
1433: xe_set_address(sc);
1434:
1435: /*
1436: * Apparently the receive byte pointer can be bad after a reset, so
1437: * we hardwire it correctly.
1438: */
1439: PAGE(sc, 0);
1440: bus_space_write_2(bst, bsh, offset + DO0, DO_CHG_OFFSET);
1441:
1442: /* Setup ethernet MAC registers. XXX Symbolic constants. */
1443: PAGE(sc, 0x40);
1444: bus_space_write_1(bst, bsh, offset + RX0MSK,
1445: PKT_TOO_LONG | CRC_ERR | RX_OVERRUN | RX_ABORT | RX_OK);
1446: bus_space_write_1(bst, bsh, offset + TX0MSK,
1447: CARRIER_LOST | EXCESSIVE_COLL | TX_UNDERRUN | LATE_COLLISION |
1448: SQE | TX_ABORT | TX_OK);
1449: if (!(sc->sc_flags & XEF_DINGO))
1450: /* XXX From Linux, dunno what 0xb0 means. */
1451: bus_space_write_1(bst, bsh, offset + TX1MSK, 0xb0);
1452: bus_space_write_1(bst, bsh, offset + RXST0, 0);
1453: bus_space_write_1(bst, bsh, offset + TXST0, 0);
1454: bus_space_write_1(bst, bsh, offset + TXST1, 0);
1455:
1456: /* Enable MII function if available. */
1457: if (LIST_FIRST(&sc->sc_mii.mii_phys)) {
1458: PAGE(sc, 2);
1459: bus_space_write_1(bst, bsh, offset + MSR,
1460: bus_space_read_1(bst, bsh, offset + MSR) | SELECT_MII);
1461: DELAY(20000);
1462: } else {
1463: PAGE(sc, 0);
1464:
1465: /* XXX Do we need to do this? */
1466: PAGE(sc, 0x42);
1467: bus_space_write_1(bst, bsh, offset + SWC1, SWC1_AUTO_MEDIA);
1468: DELAY(50000);
1469:
1470: /* XXX Linux probes the media here. */
1471: }
1472:
1473: /* Configure the LED registers. */
1474: PAGE(sc, 2);
1475:
1476: /* XXX This is not good for 10base2. */
1477: bus_space_write_1(bst, bsh, offset + LED,
1478: LED_TX_ACT << LED1_SHIFT | LED_10MB_LINK << LED0_SHIFT);
1479: if (sc->sc_flags & XEF_DINGO)
1480: bus_space_write_1(bst, bsh, offset + LED3,
1481: LED_100MB_LINK << LED3_SHIFT);
1482:
1483: /* Enable receiver and go online. */
1484: PAGE(sc, 0x40);
1485: bus_space_write_1(bst, bsh, offset + CMD0, ENABLE_RX | ONLINE);
1486:
1487: #if 0
1488: /* XXX Linux does this here - is it necessary? */
1489: PAGE(sc, 1);
1490: bus_space_write_1(bst, bsh, offset + IMR0, 0xff);
1491: if (!(sc->sc_flags & XEF_DINGO))
1492: /* XXX What is this? Not for Dingo at least. */
1493: bus_space_write_1(bst, bsh, offset + IMR1, 1);
1494: #endif
1495:
1496: /* Enable interrupts. */
1497: PAGE(sc, 0);
1498: bus_space_write_1(bst, bsh, offset + CR, ENABLE_INT);
1499:
1500: /* XXX This is pure magic for me, found in the Linux driver. */
1501: if ((sc->sc_flags & (XEF_DINGO | XEF_MODEM)) == XEF_MODEM) {
1502: if ((bus_space_read_1(bst, bsh, offset + 0x10) & 0x01) == 0)
1503: /* Unmask the master interrupt bit. */
1504: bus_space_write_1(bst, bsh, offset + 0x10, 0x11);
1505: }
1506:
1507: /*
1508: * The Linux driver says this:
1509: * We should switch back to page 0 to avoid a bug in revision 0
1510: * where regs with offset below 8 can't be read after an access
1511: * to the MAC registers.
1512: */
1513: PAGE(sc, 0);
1514: }
1515:
1516: #ifdef XEDEBUG
1517: void
1518: xe_reg_dump(sc)
1519: struct xe_softc *sc;
1520: {
1521: int page, i;
1522: bus_space_tag_t bst = sc->sc_bst;
1523: bus_space_handle_t bsh = sc->sc_bsh;
1524: bus_size_t offset = sc->sc_offset;
1525:
1526: printf("%x: Common registers: ", sc->sc_dev.dv_xname);
1527: for (i = 0; i < 8; i++) {
1528: printf(" %2.2x", bus_space_read_1(bst, bsh, offset + i));
1529: }
1530: printf("\n");
1531:
1532: for (page = 0; page < 8; page++) {
1533: printf("%s: Register page %2.2x: ", sc->sc_dev.dv_xname, page);
1534: PAGE(sc, page);
1535: for (i = 8; i < 16; i++) {
1536: printf(" %2.2x",
1537: bus_space_read_1(bst, bsh, offset + i));
1538: }
1539: printf("\n");
1540: }
1541:
1542: for (page = 0x40; page < 0x5f; page++) {
1543: if (page == 0x43 || (page >= 0x46 && page <= 0x4f) ||
1544: (page >= 0x51 && page <= 0x5e))
1545: continue;
1546: printf("%s: Register page %2.2x: ", sc->sc_dev.dv_xname, page);
1547: PAGE(sc, page);
1548: for (i = 8; i < 16; i++) {
1549: printf(" %2.2x",
1550: bus_space_read_1(bst, bsh, offset + i));
1551: }
1552: printf("\n");
1553: }
1554: }
1555: #endif /* XEDEBUG */
CVSweb