Annotation of sys/dev/isa/if_ec.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_ec.c,v 1.10 2006/10/20 17:02:24 brad Exp $ */
2: /* $NetBSD: if_ec.c,v 1.9 1998/07/05 06:49:12 jonathan Exp $ */
3:
4: /*-
5: * Copyright (c) 1997, 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: * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
43: * adapters.
44: *
45: * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
46: *
47: * Copyright (C) 1993, David Greenman. This software may be used, modified,
48: * copied, distributed, and sold, in both source and binary form provided that
49: * the above copyright and these terms are retained. Under no circumstances is
50: * the author responsible for the proper functioning of this software, nor does
51: * the author assume any responsibility for damages incurred with its use.
52: */
53:
54: /*
55: * Device driver for the 3Com Etherlink II (3c503).
56: */
57:
58: #include "bpfilter.h"
59:
60: #include <sys/param.h>
61: #include <sys/systm.h>
62: #include <sys/device.h>
63: #include <sys/socket.h>
64: #include <sys/mbuf.h>
65: #include <sys/syslog.h>
66:
67: #include <net/if.h>
68: #include <net/if_dl.h>
69: #include <net/if_types.h>
70: #include <net/if_media.h>
71:
72: #ifdef INET
73: #include <netinet/in.h>
74: #include <netinet/in_systm.h>
75: #include <netinet/in_var.h>
76: #include <netinet/ip.h>
77: #include <netinet/if_ether.h>
78: #endif
79:
80: #if NBPFILTER > 0
81: #include <net/bpf.h>
82: #endif
83:
84: #include <machine/bus.h>
85: #include <machine/intr.h>
86:
87: #include <dev/isa/isareg.h>
88: #include <dev/isa/isavar.h>
89:
90: #include <dev/ic/dp8390reg.h>
91: #include <dev/ic/dp8390var.h>
92:
93: #include <dev/isa/if_ecreg.h>
94:
95: struct ec_softc {
96: struct dp8390_softc sc_dp8390;
97:
98: bus_space_tag_t sc_asict; /* space tag for ASIC */
99: bus_space_handle_t sc_asich; /* space handle for ASIC */
100:
101: int sc_16bitp; /* are we 16 bit? */
102:
103: void *sc_ih; /* interrupt handle */
104: };
105:
106: int ec_probe(struct device *, void *, void *);
107: void ec_attach(struct device *, struct device *, void *);
108:
109: struct cfattach ec_ca = {
110: sizeof(struct ec_softc), ec_probe, ec_attach
111: };
112:
113: int ec_set_media(struct ec_softc *, int);
114:
115: void ec_media_init(struct dp8390_softc *);
116:
117: int ec_mediachange(struct dp8390_softc *);
118: void ec_mediastatus(struct dp8390_softc *, struct ifmediareq *);
119:
120: void ec_init_card(struct dp8390_softc *);
121: int ec_write_mbuf(struct dp8390_softc *, struct mbuf *, int);
122: int ec_ring_copy(struct dp8390_softc *, int, caddr_t, u_short);
123: void ec_read_hdr(struct dp8390_softc *, int, struct dp8390_ring *);
124: int ec_fake_test_mem(struct dp8390_softc *);
125: int ec_test_mem(struct dp8390_softc *);
126:
127: __inline void ec_readmem(struct ec_softc *, int, u_int8_t *, int);
128:
129: static const int ec_iobase[] = {
130: 0x2e0, 0x2a0, 0x280, 0x250, 0x350, 0x330, 0x310, 0x300,
131: };
132: #define NEC_IOBASE (sizeof(ec_iobase) / sizeof(ec_iobase[0]))
133:
134: static const int ec_membase[] = {
135: MADDRUNK, MADDRUNK, MADDRUNK, MADDRUNK, 0xc8000, 0xcc000,
136: 0xd8000, 0xdc000,
137: };
138: #define NEC_MEMBASE (sizeof(ec_membase) / sizeof(ec_membase[0]))
139:
140: struct cfdriver ec_cd = {
141: NULL, "ec", DV_IFNET
142: };
143:
144: int
145: ec_probe(struct device *parent, void *match, void *aux)
146: {
147: struct isa_attach_args *ia = aux;
148: bus_space_tag_t nict, asict, memt;
149: bus_space_handle_t nich, asich, memh;
150: bus_size_t memsize;
151: int nich_valid, asich_valid, memh_valid;
152: int i, rv = 0;
153: u_int8_t x;
154:
155: nict = asict = ia->ia_iot;
156: memt = ia->ia_memt;
157:
158: nich_valid = asich_valid = memh_valid = 0;
159:
160: /*
161: * Hmm, a 16-bit card has 16k of memory, but only an 8k window
162: * to it.
163: */
164: memsize = 8192;
165:
166: /* Disallow wildcarded i/o addresses. */
167: if (ia->ia_iobase == -1 /* ISACF_PORT_DEFAULT */)
168: return (0);
169:
170: /* Disallow wildcarded mem address. */
171: if (ia->ia_maddr == -1 /* ISACF_IOMEM_DEFAULT */)
172: return (0);
173:
174: /* Validate the i/o base. */
175: for (i = 0; i < NEC_IOBASE; i++)
176: if (ia->ia_iobase == ec_iobase[i])
177: break;
178: if (i == NEC_IOBASE)
179: return (0);
180:
181: /* Validate the mem base. */
182: for (i = 0; i < NEC_MEMBASE; i++) {
183: if (ec_membase[i] == MADDRUNK)
184: continue;
185: if (ia->ia_maddr == ec_membase[i])
186: break;
187: }
188: if (i == NEC_MEMBASE)
189: return (0);
190:
191: /* Attempt to map the NIC space. */
192: if (bus_space_map(nict, ia->ia_iobase + ELINK2_NIC_OFFSET,
193: ELINK2_NIC_PORTS, 0, &nich))
194: goto out;
195: nich_valid = 1;
196:
197: /* Attempt to map the ASIC space. */
198: if (bus_space_map(asict, ia->ia_iobase + ELINK2_ASIC_OFFSET,
199: ELINK2_ASIC_PORTS, 0, &asich))
200: goto out;
201: asich_valid = 1;
202:
203: /* Attempt to map the memory space. */
204: if (bus_space_map(memt, ia->ia_maddr, memsize, 0, &memh))
205: goto out;
206: memh_valid = 1;
207:
208: /*
209: * Verify that the kernel configured I/O address matches the
210: * board configured I/O address.
211: *
212: * This is really only useful to see if something that looks like
213: * the board is there; after all, we're already talking to it at
214: * this point.
215: */
216: x = bus_space_read_1(asict, asich, ELINK2_BCFR);
217: if (x == 0 || (x & (x - 1)) != 0)
218: goto out;
219: i = ffs(x) - 1;
220: if (ia->ia_iobase != ec_iobase[i])
221: goto out;
222:
223: /*
224: * ...and for the memory address. Note we do not support
225: * cards configured with shared memory disabled.
226: */
227: x = bus_space_read_1(asict, asich, ELINK2_PCFR);
228: if (x == 0 || (x & (x - 1)) != 0)
229: goto out;
230: i = ffs(x) - 1;
231: if (ia->ia_maddr != ec_membase[i])
232: goto out;
233:
234: /* So, we say we've found it! */
235: ia->ia_iosize = ELINK2_NIC_PORTS;
236: ia->ia_msize = memsize;
237: rv = 1;
238:
239: out:
240: if (nich_valid)
241: bus_space_unmap(nict, nich, ELINK2_NIC_PORTS);
242: if (asich_valid)
243: bus_space_unmap(asict, asich, ELINK2_ASIC_PORTS);
244: if (memh_valid)
245: bus_space_unmap(memt, memh, memsize);
246: return (rv);
247: }
248:
249: void
250: ec_attach(struct device *parent, struct device *self, void *aux)
251: {
252: struct ec_softc *esc = (struct ec_softc *)self;
253: struct dp8390_softc *sc = &esc->sc_dp8390;
254: struct isa_attach_args *ia = aux;
255: bus_space_tag_t nict, asict, memt;
256: bus_space_handle_t nich, asich, memh;
257: bus_size_t memsize;
258: u_int8_t tmp;
259: int i;
260:
261: printf("\n");
262:
263: nict = asict = ia->ia_iot;
264: memt = ia->ia_memt;
265:
266: /*
267: * Hmm, a 16-bit card has 16k of memory, but only an 8k window
268: * to it.
269: */
270: memsize = 8192;
271:
272: /* Map the NIC space. */
273: if (bus_space_map(nict, ia->ia_iobase + ELINK2_NIC_OFFSET,
274: ELINK2_NIC_PORTS, 0, &nich)) {
275: printf("%s: can't map nic i/o space\n",
276: sc->sc_dev.dv_xname);
277: return;
278: }
279:
280: /* Map the ASIC space. */
281: if (bus_space_map(asict, ia->ia_iobase + ELINK2_ASIC_OFFSET,
282: ELINK2_ASIC_PORTS, 0, &asich)) {
283: printf("%s: can't map asic i/o space\n",
284: sc->sc_dev.dv_xname);
285: return;
286: }
287:
288: /* Map the memory space. */
289: if (bus_space_map(memt, ia->ia_maddr, memsize, 0, &memh)) {
290: printf("%s: can't map shared memory\n",
291: sc->sc_dev.dv_xname);
292: return;
293: }
294:
295: esc->sc_asict = asict;
296: esc->sc_asich = asich;
297:
298: sc->sc_regt = nict;
299: sc->sc_regh = nich;
300:
301: sc->sc_buft = memt;
302: sc->sc_bufh = memh;
303:
304: /* Interface is always enabled. */
305: sc->sc_enabled = 1;
306:
307: /* Registers are linear. */
308: for (i = 0; i < 16; i++)
309: sc->sc_reg_map[i] = i;
310:
311: /* Now we can use the NIC_{GET,PUT}() macros. */
312:
313: /*
314: * Reset NIC and ASIC. Enable on-board transeiver throughout
315: * reset sequence since it will lock up if the cable isn't
316: * connected if we don't.
317: */
318: bus_space_write_1(asict, asich, ELINK2_CR,
319: ELINK2_CR_RST | ELINK2_CR_XSEL);
320:
321: /* Wait for a while, then un-reset it. */
322: delay(50);
323:
324: /*
325: * The 3Com ASIC defaults to rather strange settings for the CR
326: * after a reset. It's important to set it again after the
327: * following write (this is done when we map the PROM below).
328: */
329: bus_space_write_1(asict, asich, ELINK2_CR, ELINK2_CR_XSEL);
330:
331: /* Wait a bit for the NIC to recover from the reset. */
332: delay(5000);
333:
334: /*
335: * Get the station address from on-board ROM.
336: *
337: * First, map Ethernet address PROM over the top of where the NIC
338: * registers normally appear.
339: */
340: bus_space_write_1(asict, asich, ELINK2_CR,
341: ELINK2_CR_XSEL | ELINK2_CR_EALO);
342:
343: for (i = 0; i < ETHER_ADDR_LEN; i++)
344: sc->sc_arpcom.ac_enaddr[i] = NIC_GET(nict, nich, i);
345:
346: /*
347: * Unmap PROM - select NIC registers. The proper setting of the
348: * transciever is set in later in ec_init_card() via dp8390_init().
349: */
350: bus_space_write_1(asict, asich, ELINK2_CR, ELINK2_CR_XSEL);
351:
352: /* Determine if this is an 8-bit or 16-bit board. */
353:
354: /* Select page 0 registers. */
355: NIC_PUT(nict, nich, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
356:
357: /*
358: * Attempt to clear WTS. If it doesn't clear, then this is a
359: * 16-bit board.
360: */
361: NIC_PUT(nict, nich, ED_P0_DCR, 0);
362:
363: /* Select page 2 registers. */
364: NIC_PUT(nict, nich, ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_2 | ED_CR_STP);
365:
366: /* The 3c503 forces the WTS bit to a one if this is a 16-bit board. */
367: if (NIC_GET(nict, nich, ED_P2_DCR) & ED_DCR_WTS)
368: esc->sc_16bitp = 1;
369: else
370: esc->sc_16bitp = 0;
371:
372: printf("%s: 3Com 3c503 Ethernet (%s-bit)",
373: sc->sc_dev.dv_xname, esc->sc_16bitp ? "16" : "8");
374:
375: /* Select page 0 registers. */
376: NIC_PUT(nict, nich, ED_P2_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
377:
378: sc->cr_proto = ED_CR_RD2;
379:
380: /*
381: * DCR gets:
382: *
383: * FIFO threshold to 8, No auto-init Remote DMA,
384: * byte order=80x86.
385: *
386: * 16-bit cards also get word-wide DMA transfers.
387: */
388: sc->dcr_reg = ED_DCR_FT1 | ED_DCR_LS |
389: (esc->sc_16bitp ? ED_DCR_WTS : 0);
390:
391: sc->test_mem = ec_fake_test_mem;
392: sc->ring_copy = ec_ring_copy;
393: sc->write_mbuf = ec_write_mbuf;
394: sc->read_hdr = ec_read_hdr;
395:
396: sc->sc_media_init = ec_media_init;
397:
398: sc->sc_mediachange = ec_mediachange;
399: sc->sc_mediastatus = ec_mediastatus;
400:
401: sc->mem_start = 0;
402: sc->mem_size = memsize;
403:
404: /* Do generic parts of attach. */
405: if (dp8390_config(sc)) {
406: printf(": configuration failed\n");
407: return;
408: }
409:
410: /*
411: * We need to override the way dp8390_config() set up our
412: * shared memory.
413: *
414: * We have an entire 8k window to put the transmit buffers on the
415: * 16-bit boards. But since the 16bit 3c503's shared memory is only
416: * fast enough to overlap the loading of one full-size packet, trying
417: * to load more than 2 buffers can actually leave the transmitter idle
418: * during the load. So 2 seems the best value. (Although a mix of
419: * variable-sized packets might change this assumption. Nonetheless,
420: * we optimize for linear transfers of same-size packets.)
421: */
422: if (esc->sc_16bitp) {
423: if (sc->sc_dev.dv_cfdata->cf_flags & DP8390_NO_MULTI_BUFFERING)
424: sc->txb_cnt = 1;
425: else
426: sc->txb_cnt = 2;
427:
428: sc->tx_page_start = ELINK2_TX_PAGE_OFFSET_16BIT;
429: sc->rec_page_start = ELINK2_RX_PAGE_OFFSET_16BIT;
430: sc->rec_page_stop = (memsize >> ED_PAGE_SHIFT) +
431: sc->rec_page_start;
432: sc->mem_ring = sc->mem_start;
433: } else {
434: sc->txb_cnt = 1;
435: sc->tx_page_start = ELINK2_TX_PAGE_OFFSET_8BIT;
436: sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE;
437: sc->rec_page_stop = (memsize >> ED_PAGE_SHIFT) +
438: sc->tx_page_start;
439: sc->mem_ring = sc->mem_start +
440: (ED_TXBUF_SIZE << ED_PAGE_SHIFT);
441: }
442:
443: /*
444: * Initialize CA page start/stop registers. Probably only needed
445: * if doing DMA, but what the Hell.
446: */
447: bus_space_write_1(asict, asich, ELINK2_PSTR, sc->rec_page_start);
448: bus_space_write_1(asict, asich, ELINK2_PSPR, sc->rec_page_stop);
449:
450: /*
451: * Program the IRQ.
452: */
453: switch (ia->ia_irq) {
454: case 9: tmp = ELINK2_IDCFR_IRQ2; break;
455: case 3: tmp = ELINK2_IDCFR_IRQ3; break;
456: case 4: tmp = ELINK2_IDCFR_IRQ4; break;
457: case 5: tmp = ELINK2_IDCFR_IRQ5; break;
458: break;
459:
460: case IRQUNK:
461: printf("%s: wildcarded IRQ is not allowed\n",
462: sc->sc_dev.dv_xname);
463: return;
464:
465: default:
466: printf("%s: invalid IRQ %d, must be 3, 4, 5, or 9\n",
467: sc->sc_dev.dv_xname, ia->ia_irq);
468: return;
469: }
470:
471: bus_space_write_1(asict, asich, ELINK2_IDCFR, tmp);
472:
473: /*
474: * Initialize the GA configuration register. Set bank and enable
475: * shared memory.
476: */
477: bus_space_write_1(asict, asich, ELINK2_GACFR,
478: ELINK2_GACFR_RSEL | ELINK2_GACFR_MBS0);
479:
480: /*
481: * Intialize "Vector Pointer" registers. These gawd-awful things
482: * are compared to 20 bits of the address on the ISA, and if they
483: * match, the shared memory is disabled. We se them to 0xffff0...
484: * allegedly the reset vector.
485: */
486: bus_space_write_1(asict, asich, ELINK2_VPTR2, 0xff);
487: bus_space_write_1(asict, asich, ELINK2_VPTR1, 0xff);
488: bus_space_write_1(asict, asich, ELINK2_VPTR0, 0x00);
489:
490: /*
491: * Now run the real memory test.
492: */
493: if (ec_test_mem(sc)) {
494: printf("%s: memory test failed\n", sc->sc_dev.dv_xname);
495: return;
496: }
497:
498: /* Establish interrupt handler. */
499: esc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
500: IPL_NET, dp8390_intr, sc, sc->sc_dev.dv_xname);
501: if (esc->sc_ih == NULL)
502: printf("%s: can't establish interrupt\n", sc->sc_dev.dv_xname);
503: }
504:
505: int
506: ec_fake_test_mem(struct dp8390_softc *sc)
507: {
508: /*
509: * We have to do this after we initialize the GA, but we
510: * have to do that after calling dp8390_config(), which
511: * wants to test memory. Put this noop here, and then
512: * actually test memory later.
513: */
514: return (0);
515: }
516:
517: int
518: ec_test_mem(struct dp8390_softc *sc)
519: {
520: struct ec_softc *esc = (struct ec_softc *)sc;
521: bus_space_tag_t memt = sc->sc_buft;
522: bus_space_handle_t memh = sc->sc_bufh;
523: bus_size_t memsize = sc->mem_size;
524: int i;
525:
526: if (esc->sc_16bitp)
527: bus_space_set_region_2(memt, memh, 0, 0, memsize >> 1);
528: else
529: bus_space_set_region_1(memt, memh, 0, 0, memsize);
530:
531: if (esc->sc_16bitp) {
532: for (i = 0; i < memsize; i += 2) {
533: if (bus_space_read_2(memt, memh, i) != 0)
534: goto fail;
535: }
536: } else {
537: for (i = 0; i < memsize; i++) {
538: if (bus_space_read_1(memt, memh, i) != 0)
539: goto fail;
540: }
541: }
542:
543: return (0);
544:
545: fail:
546: printf("%s: failed to clear shared memory at offset 0x%x\n",
547: sc->sc_dev.dv_xname, i);
548: return (1);
549: }
550:
551: /*
552: * Given a NIC memory source address and a host memory destination address,
553: * copy 'len' from NIC to host using shared memory. The 'len' is rounded
554: * up to a word - ok as long as mbufs are word-sized.
555: */
556: __inline void
557: ec_readmem(struct ec_softc *esc, int from, u_int8_t *to, int len)
558: {
559: bus_space_tag_t memt = esc->sc_dp8390.sc_buft;
560: bus_space_handle_t memh = esc->sc_dp8390.sc_bufh;
561:
562: if (len & 1)
563: ++len;
564:
565: if (esc->sc_16bitp)
566: bus_space_read_region_2(memt, memh, from, (u_int16_t *)to,
567: len >> 1);
568: else
569: bus_space_read_region_1(memt, memh, from, to, len);
570: }
571:
572: int
573: ec_write_mbuf(struct dp8390_softc *sc, struct mbuf *m, int buf)
574: {
575: struct ec_softc *esc = (struct ec_softc *)sc;
576: bus_space_tag_t asict = esc->sc_asict;
577: bus_space_handle_t asich = esc->sc_asich;
578: bus_space_tag_t memt = esc->sc_dp8390.sc_buft;
579: bus_space_handle_t memh = esc->sc_dp8390.sc_bufh;
580: u_int8_t *data, savebyte[2];
581: int savelen, len, leftover;
582: #ifdef DIAGNOSTIC
583: u_int8_t *lim;
584: #endif
585:
586: savelen = m->m_pkthdr.len;
587:
588: /*
589: * 8-bit boards are simple: we're already in the correct
590: * page, and no alignment tricks are necessary.
591: */
592: if (esc->sc_16bitp == 0) {
593: for (; m != NULL; buf += m->m_len, m = m->m_next)
594: bus_space_write_region_1(memt, memh, buf,
595: mtod(m, u_int8_t *), m->m_len);
596: return (savelen);
597: }
598:
599: /*
600: * If it's a 16-bit board, we have transmit buffers
601: * in a different page; switch to it.
602: */
603: if (esc->sc_16bitp)
604: bus_space_write_1(asict, asich, ELINK2_GACFR,
605: ELINK2_GACFR_RSEL);
606:
607: /* Start out with no leftover data. */
608: leftover = 0;
609: savebyte[0] = savebyte[1] = 0;
610:
611: for (; m != NULL; m = m->m_next) {
612: len = m->m_len;
613: if (len == 0)
614: continue;
615: data = mtod(m, u_int8_t *);
616: #ifdef DIAGNOSTIC
617: lim = data + len;
618: #endif
619: while (len > 0) {
620: if (leftover) {
621: /*
622: * Data left over (from mbuf or realignment).
623: * Buffer the next byte, and write it and
624: * the leftover data out.
625: */
626: savebyte[1] = *data++;
627: len--;
628: bus_space_write_2(memt, memh, buf,
629: *(u_int16_t *)savebyte);
630: buf += 2;
631: leftover = 0;
632: } else if (ALIGNED_POINTER(data, u_int16_t) == 0) {
633: /*
634: * Unaligned data; buffer the next byte.
635: */
636: savebyte[0] = *data++;
637: len--;
638: leftover = 1;
639: } else {
640: /*
641: * Aligned data; output contiguous words as
642: * much as we can, then buffer the remaining
643: * byte, if any.
644: */
645: leftover = len & 1;
646: len &= ~1;
647: bus_space_write_region_2(memt, memh, buf,
648: (u_int16_t *)data, len >> 1);
649: data += len;
650: buf += len;
651: if (leftover)
652: savebyte[0] = *data++;
653: len = 0;
654: }
655: }
656: if (len < 0)
657: panic("ec_write_mbuf: negative len");
658: #ifdef DIAGNOSTIC
659: if (data != lim)
660: panic("ec_write_mbuf: data != lim");
661: #endif
662: }
663: if (leftover) {
664: savebyte[1] = 0;
665: bus_space_write_2(memt, memh, buf, *(u_int16_t *)savebyte);
666: }
667:
668: /*
669: * Switch back to receive page.
670: */
671: if (esc->sc_16bitp)
672: bus_space_write_1(asict, asich, ELINK2_GACFR,
673: ELINK2_GACFR_RSEL | ELINK2_GACFR_MBS0);
674:
675: return (savelen);
676: }
677:
678: int
679: ec_ring_copy(struct dp8390_softc *sc, int src, caddr_t dst,
680: u_short amount)
681: {
682: struct ec_softc *esc = (struct ec_softc *)sc;
683: u_short tmp_amount;
684:
685: /* Does copy wrap to lower addr in ring buffer? */
686: if (src + amount > sc->mem_end) {
687: tmp_amount = sc->mem_end - src;
688:
689: /* Copy amount up to end of NIC memory. */
690: ec_readmem(esc, src, dst, tmp_amount);
691:
692: amount -= tmp_amount;
693: src = sc->mem_ring;
694: dst += tmp_amount;
695: }
696:
697: ec_readmem(esc, src, dst, amount);
698:
699: return (src + amount);
700: }
701:
702: void
703: ec_read_hdr(struct dp8390_softc *sc, int packet_ptr,
704: struct dp8390_ring *packet_hdrp)
705: {
706: struct ec_softc *esc = (struct ec_softc *)sc;
707:
708: ec_readmem(esc, packet_ptr, (u_int8_t *)packet_hdrp,
709: sizeof(struct dp8390_ring));
710: #if BYTE_ORDER == BIG_ENDIAN
711: packet_hdrp->count = swap16(packet_hdrp->count);
712: #endif
713: }
714:
715: void
716: ec_media_init(struct dp8390_softc *sc)
717: {
718: ifmedia_init(&sc->sc_media, 0, dp8390_mediachange, dp8390_mediastatus);
719: ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_2, 0, NULL);
720: ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_5, 0, NULL);
721: ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_10_2);
722: }
723:
724: int
725: ec_mediachange(struct dp8390_softc *sc)
726: {
727: struct ec_softc *esc = (struct ec_softc *)sc;
728: struct ifmedia *ifm = &sc->sc_media;
729:
730: return (ec_set_media(esc, ifm->ifm_media));
731: }
732:
733: void
734: ec_mediastatus(struct dp8390_softc *sc, struct ifmediareq *ifmr)
735: {
736: struct ifmedia *ifm = &sc->sc_media;
737:
738: /*
739: * The currently selected media is always the active media.
740: */
741: ifmr->ifm_active = ifm->ifm_cur->ifm_media;
742: }
743:
744: void
745: ec_init_card(struct dp8390_softc *sc)
746: {
747: struct ec_softc *esc = (struct ec_softc *)sc;
748: struct ifmedia *ifm = &sc->sc_media;
749:
750: (void) ec_set_media(esc, ifm->ifm_cur->ifm_media);
751: }
752:
753: int
754: ec_set_media(struct ec_softc *esc, int media)
755: {
756: u_int8_t new;
757:
758: if (IFM_TYPE(media) != IFM_ETHER)
759: return (EINVAL);
760:
761: switch (IFM_SUBTYPE(media)) {
762: case IFM_10_2:
763: new = ELINK2_CR_XSEL;
764: break;
765:
766: case IFM_10_5:
767: new = 0;
768: break;
769:
770: default:
771: return (EINVAL);
772: }
773:
774: bus_space_write_1(esc->sc_asict, esc->sc_asich, ELINK2_CR, new);
775: return (0);
776: }
CVSweb