1 /* $NetBSD: if_eh.c,v 1.14 2008/04/28 20:23:09 martin Exp $ */
4 * Copyright (c) 2000 Ben Harris
5 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
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.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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.
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
36 * Copyright (C) 1993, David Greenman. This software may be used, modified,
37 * copied, distributed, and sold, in both source and binary form provided that
38 * the above copyright and these terms are retained. Under no circumstances is
39 * the author responsible for the proper functioning of this software, nor does
40 * the author assume any responsibility for damages incurred with its use.
43 * if_eh.c -- driver for i-cubed EtherLan 100-, 200- and 500-series cards.
46 #include <sys/param.h>
48 __KERNEL_RCSID(0, "$NetBSD: if_eh.c,v 1.14 2008/04/28 20:23:09 martin Exp $");
50 #include <sys/systm.h>
51 #include <sys/device.h>
52 #include <sys/socket.h>
54 #include <sys/reboot.h>
55 #include <sys/syslog.h>
58 #include <net/if_dl.h>
59 #include <net/if_types.h>
60 #include <net/if_media.h>
62 #include <net/if_ether.h>
64 #include <sys/bswap.h>
65 #include <machine/bus.h>
66 #include <machine/irq.h>
68 #ifndef __BUS_SPACE_HAS_STREAM_METHODS
69 #define bus_space_write_stream_2 bus_space_write_2
70 #define bus_space_write_multi_stream_2 bus_space_write_multi_2
71 #define bus_space_read_multi_stream_2 bus_space_read_multi_2
72 #endif /* __BUS_SPACE_HAS_STREAM_METHODS */
74 #include <dev/ic/dp8390reg.h>
75 #include <dev/ic/dp8390var.h>
77 #include <dev/podulebus/podulebus.h>
78 #include <dev/podulebus/podules.h>
79 #include <arch/acorn26/podulebus/if_ehreg.h>
83 #define EH_MEDIA_2_T 2
84 #define EH_MEDIA_FL_T 3
87 struct dp8390_softc sc_dp
;
88 bus_space_tag_t sc_datat
;
89 bus_space_handle_t sc_datah
;
90 bus_space_tag_t sc_ctlt
;
91 bus_space_handle_t sc_ctlh
;
92 bus_space_tag_t sc_ctl2t
;
93 bus_space_handle_t sc_ctl2h
;
95 struct evcnt sc_intrcnt
;
97 #define EHF_16BIT 0x01
101 u_int8_t sc_ctrl
; /* Current control reg state */
104 int eh_write_mbuf(struct dp8390_softc
*, struct mbuf
*, int);
105 int eh_ring_copy(struct dp8390_softc
*, int, void *, u_short
);
106 void eh_read_hdr(struct dp8390_softc
*, int, struct dp8390_ring
*);
107 int eh_test_mem(struct dp8390_softc
*);
109 void eh_writemem(struct eh_softc
*, u_int8_t
*, int, size_t);
110 void eh_readmem(struct eh_softc
*, int, u_int8_t
*, size_t);
111 static void eh_init_card(struct dp8390_softc
*);
112 static int eh_availmedia(struct eh_softc
*);
113 /*static*/ int eh_identifymau(struct eh_softc
*);
115 void eh_media_init(struct dp8390_softc
*);
118 static int eh_mediachange(struct dp8390_softc
*);
119 static void eh_mediastatus(struct dp8390_softc
*, struct ifmediareq
*);
121 /* autoconfiguration glue */
122 static int eh_match(device_t
, cfdata_t
, void *);
123 static void eh_attach(device_t
, device_t
, void *);
125 CFATTACH_DECL_NEW(eh
, sizeof(struct eh_softc
),
126 eh_match
, eh_attach
, NULL
, NULL
);
129 eh_match(device_t parent
, cfdata_t cf
, void *aux
)
131 struct podulebus_attach_args
*pa
= aux
;
133 switch (pa
->pa_product
) {
134 case PODULE_ETHERLAN100
:
135 case PODULE_ETHERLAN100AEH
:
136 case PODULE_ETHERLAN200
:
137 case PODULE_ETHERLAN200AEH
:
138 case PODULE_ETHERLAN500
:
139 case PODULE_ETHERLAN500AEH
:
145 /* XXX 10BASE-FL on E513 */
146 static int media_only2
[] = { IFM_ETHER
| IFM_10_2
};
147 static int media_onlyt
[] = { IFM_ETHER
| IFM_10_T
};
148 static int media_2andt
[] =
149 { IFM_ETHER
| IFM_AUTO
, IFM_ETHER
| IFM_10_2
, IFM_ETHER
| IFM_10_T
};
150 static const struct {
160 eh_attach(device_t parent
, device_t self
, void *aux
)
162 struct podulebus_attach_args
*pa
= aux
;
163 struct eh_softc
*sc
= device_private(self
);
164 struct dp8390_softc
*dsc
= &sc
->sc_dp
;
165 int mediaset
, mautype
;
172 /* Canonicalise card type. */
173 switch (pa
->pa_product
) {
174 case PODULE_ETHERLAN100
:
175 case PODULE_ETHERLAN100AEH
:
176 sc
->sc_type
= PODULE_ETHERLAN100
;
178 case PODULE_ETHERLAN200
:
179 case PODULE_ETHERLAN200AEH
:
180 sc
->sc_type
= PODULE_ETHERLAN200
;
182 case PODULE_ETHERLAN500
:
183 case PODULE_ETHERLAN500AEH
:
184 sc
->sc_type
= PODULE_ETHERLAN500
;
188 /* Memory size and width varies. */
190 switch (sc
->sc_type
) {
191 case PODULE_ETHERLAN200
:
192 sc
->sc_flags
|= EHF_MAU
;
194 case PODULE_ETHERLAN100
:
195 printf(": 8-bit, 32 KB RAM");
196 dsc
->mem_size
= 0x8000;
198 case PODULE_ETHERLAN500
:
199 printf(": 16-bit, 64 KB RAM");
200 sc
->sc_flags
|= EHF_16BIT
;
201 dsc
->mem_size
= 0x10000;
205 /* Set up bus spaces */
206 dsc
->sc_regt
= pa
->pa_mod_t
;
207 bus_space_subregion(dsc
->sc_regt
, pa
->pa_mod_h
, EH_DP8390
, 0x10,
209 sc
->sc_datat
= pa
->pa_mod_t
;
210 bus_space_subregion(sc
->sc_datat
, pa
->pa_mod_h
, EH_DATA
, 1,
212 sc
->sc_ctlt
= pa
->pa_fast_t
;
213 bus_space_subregion(sc
->sc_ctlt
, pa
->pa_fast_h
, EH_CTRL
, 1,
215 sc
->sc_ctl2t
= pa
->pa_fast_t
;
216 bus_space_subregion(sc
->sc_ctl2t
, pa
->pa_fast_h
, EH_CTRL2
, 1,
220 /* dsc->rcr_proto? */
222 /* Follow NE2000 driver here. */
223 dsc
->dcr_reg
= ED_DCR_FT1
| ED_DCR_LS
;
224 if (sc
->sc_flags
& EHF_16BIT
)
225 dsc
->dcr_reg
|= ED_DCR_WTS
;
227 /* Set up callbacks */
228 dsc
->test_mem
= eh_test_mem
;
229 dsc
->init_card
= eh_init_card
;
230 dsc
->read_hdr
= eh_read_hdr
;
232 dsc
->ring_copy
= eh_ring_copy
;
233 dsc
->write_mbuf
= eh_write_mbuf
;
235 /* dsc->sc_disable */
236 dsc
->sc_mediachange
= eh_mediachange
;
237 dsc
->sc_mediastatus
= eh_mediastatus
;
238 dsc
->sc_media_init
= eh_media_init
;
239 /* dsc->sc_media_fini */
241 for (i
= 0; i
< 16; i
++)
242 dsc
->sc_reg_map
[i
] = i
;
246 if (sc
->sc_flags
& EHF_MAU
) {
247 mautype
= eh_identifymau(sc
);
249 case EH200_MAUID_10_2
:
250 printf(", 10BASE2 MAU");
251 mediaset
= EH_MEDIA_2
;
253 case EH200_MAUID_10_T
:
254 printf(", 10BASE-T MAU");
255 mediaset
= EH_MEDIA_T
;
258 printf(", unknown MAU id %d", mautype
);
259 mediaset
= EH_MEDIA_2
; /* XXX */
263 mediaset
= eh_availmedia(sc
);
266 printf(", 10BASE2 only");
269 printf(", 10BASE-T only");
272 printf(", combo 10BASE2/-T");
276 sc
->sc_mediaset
= mediaset
;
279 /* i-cubed put everything behind the loader. */
280 podulebus_initloader(pa
);
283 * Get the Ethernet address from the device description string.
284 * This code is stolen from if_ea.c. It should be shared.
286 myaddr
= dsc
->sc_enaddr
;
287 if (pa
->pa_descr
== NULL
) {
288 printf(": No description for Ethernet address\n");
291 ptr
= strchr(pa
->pa_descr
, '(');
293 printf(": Ethernet address not found in description\n");
297 for (i
= 0; i
< ETHER_ADDR_LEN
; i
++) {
298 myaddr
[i
] = strtoul(ptr
, &ptr
, 16);
299 if (*ptr
++ != (i
== ETHER_ADDR_LEN
- 1 ? ')' : ':')) {
300 printf(": Bad Ethernet address found in "
309 evcnt_attach_dynamic(&sc
->sc_intrcnt
, EVCNT_TYPE_INTR
, NULL
,
310 device_xname(self
), "intr");
311 sc
->sc_ih
= podulebus_irq_establish(pa
->pa_ih
, IPL_NET
, dp8390_intr
,
312 &sc
->sc_dp
, &sc
->sc_intrcnt
);
314 aprint_verbose_dev(self
, "interrupting at %s\n",
315 irq_string(sc
->sc_ih
));
316 sc
->sc_ctrl
|= EH_CTRL_IE
;
317 bus_space_write_1(sc
->sc_ctlt
, sc
->sc_ctlh
, 0, sc
->sc_ctrl
);
321 eh_init_card(struct dp8390_softc
*sc
)
328 * Write an mbuf chain to the destination NIC memory address using programmed
332 eh_write_mbuf(struct dp8390_softc
*dsc
, struct mbuf
*m
, int buf
)
334 struct eh_softc
*sc
= (struct eh_softc
*)dsc
;
335 bus_space_tag_t nict
= dsc
->sc_regt
;
336 bus_space_handle_t nich
= dsc
->sc_regh
;
337 bus_space_tag_t datat
= sc
->sc_datat
;
338 bus_space_handle_t datah
= sc
->sc_datah
;
340 int maxwait
= 100; /* about 120us */
342 savelen
= m
->m_pkthdr
.len
;
343 if (savelen
< ETHER_MIN_LEN
- ETHER_CRC_LEN
) {
344 padlen
= ETHER_MIN_LEN
- ETHER_CRC_LEN
- savelen
;
345 savelen
= ETHER_MIN_LEN
- ETHER_CRC_LEN
;
350 * Set-up procedure per DP83902A data sheet:
351 * I) Write a non-zero value into RBCR0.
352 * II) Set bits RD2, RD1, and RD0 to 0, 0, and 1.
353 * III) Set RBCR0, 1 and RSAR0, 1.
354 * IV) Issue the Remote Write DMA Command (RD2, RD1, RD0 = 0, 1, 0).
357 /* Select page 0 registers. */
359 NIC_BARRIER(nict
, nich
);
360 bus_space_write_1(nict
, nich
, ED_P0_CR
,
361 ED_CR_RD2
| ED_CR_PAGE_0
| ED_CR_STA
);
362 NIC_BARRIER(nict
, nich
);
364 /* Write random number. Linux writes several, follow them. */
365 bus_space_write_1(nict
, nich
, ED_P0_RBCR0
, 123);
366 bus_space_write_1(nict
, nich
, ED_P0_RBCR1
, 123);
367 bus_space_write_1(nict
, nich
, ED_P0_RSAR0
, 123);
368 bus_space_write_1(nict
, nich
, ED_P0_RSAR1
, 123);
369 NIC_BARRIER(nict
, nich
);
371 /* Linux has a 1us pause here. Follow them. */
374 /* Select DMA read (see above) */
375 bus_space_write_1(nict
, nich
, ED_P0_CR
,
376 ED_CR_RD0
| ED_CR_PAGE_0
| ED_CR_STA
);
377 NIC_BARRIER(nict
, nich
);
379 /* Reset remote DMA complete flag. */
380 bus_space_write_1(nict
, nich
, ED_P0_ISR
, ED_ISR_RDC
);
381 NIC_BARRIER(nict
, nich
);
383 /* Set up DMA byte count. */
384 bus_space_write_1(nict
, nich
, ED_P0_RBCR0
, savelen
);
385 bus_space_write_1(nict
, nich
, ED_P0_RBCR1
, savelen
>> 8);
387 /* Set up destination address in NIC mem. */
388 bus_space_write_1(nict
, nich
, ED_P0_RSAR0
, buf
);
389 bus_space_write_1(nict
, nich
, ED_P0_RSAR1
, buf
>> 8);
391 /* Set remote DMA write. */
392 NIC_BARRIER(nict
, nich
);
393 bus_space_write_1(nict
, nich
,
394 ED_P0_CR
, ED_CR_RD1
| ED_CR_PAGE_0
| ED_CR_STA
);
395 NIC_BARRIER(nict
, nich
);
398 * Transfer the mbuf chain to the NIC memory. NE2000 cards
399 * require that data be transferred as words, and only words,
400 * so that case requires some extra code to patch over odd-length
403 if ((sc
->sc_flags
& EHF_16BIT
) == 0) {
404 /* NE1000s are easy. */
405 for (; m
!= 0; m
= m
->m_next
)
407 bus_space_write_multi_1(datat
, datah
, 0,
408 mtod(m
, u_int8_t
*), m
->m_len
);
410 for(; padlen
> 0; padlen
--)
411 bus_space_write_1(datat
, datah
, 0, 0);
414 /* NE2000s are a bit trickier. */
415 u_int8_t
*data
, savebyte
[2];
420 /* Start out with no leftover data. */
422 savebyte
[0] = savebyte
[1] = 0;
424 for (; m
!= 0; m
= m
->m_next
) {
428 data
= mtod(m
, u_int8_t
*);
435 * Data left over (from mbuf or
436 * realignment). Buffer the next
437 * byte, and write it and the
440 savebyte
[1] = *data
++;
442 bus_space_write_stream_2(datat
, datah
,
444 *(u_int16_t
*)savebyte
);
446 } else if (BUS_SPACE_ALIGNED_POINTER(data
,
449 * Unaligned data; buffer the next
452 savebyte
[0] = *data
++;
457 * Aligned data; output contiguous
458 * words as much as we can, then
459 * buffer the remaining byte, if any.
463 bus_space_write_multi_stream_2(datat
,
465 (u_int16_t
*)data
, l
>> 1);
468 savebyte
[0] = *data
++;
473 panic("eh_write_mbuf: negative len");
476 panic("eh_write_mbuf: data != lim");
481 bus_space_write_stream_2(datat
, datah
, 0,
482 *(u_int16_t
*)savebyte
);
485 for(; padlen
> 0; padlen
-= 2)
486 bus_space_write_stream_2(datat
, datah
, 0, 0);
489 NIC_BARRIER(nict
, nich
);
492 * Wait for remote DMA to complete. This is necessary because on the
493 * transmit side, data is handled internally by the NIC in bursts, and
494 * we can't start another remote DMA until this one completes. Not
495 * waiting causes really bad things to happen - like the NIC wedging
498 while (((bus_space_read_1(nict
, nich
, ED_P0_ISR
) & ED_ISR_RDC
) !=
499 ED_ISR_RDC
) && --maxwait
) {
500 bus_space_read_1(nict
, nich
, ED_P0_CRDA1
);
501 bus_space_read_1(nict
, nich
, ED_P0_CRDA0
);
502 NIC_BARRIER(nict
, nich
);
508 "%s: remote transmit DMA failed to complete "
509 "(RSAR=0x%04x, RBCR=0x%04x, CRDA=0x%02x%02x)\n",
510 device_xname(dsc
->sc_dev
), buf
, savelen
,
511 bus_space_read_1(nict
, nich
, ED_P0_CRDA1
),
512 bus_space_read_1(nict
, nich
, ED_P0_CRDA0
));
520 * Given a source and destination address, copy 'amout' of a packet from
521 * the ring buffer into a linear destination buffer. Takes into account
525 eh_ring_copy(struct dp8390_softc
*dsc
, int src
, void *dst_arg
, u_short amount
)
527 struct eh_softc
*sc
= (struct eh_softc
*)dsc
;
529 u_int8_t
*dst
= dst_arg
;
531 /* Does copy wrap to lower addr in ring buffer? */
532 if (src
+ amount
> dsc
->mem_end
) {
533 tmp_amount
= dsc
->mem_end
- src
;
535 /* Copy amount up to end of NIC memory. */
536 eh_readmem(sc
, src
, dst
, tmp_amount
);
538 amount
-= tmp_amount
;
543 eh_readmem(sc
, src
, dst
, amount
);
545 return (src
+ amount
);
549 eh_read_hdr(struct dp8390_softc
*dsc
, int buf
, struct dp8390_ring
*hdr
)
551 struct eh_softc
*sc
= (struct eh_softc
*)dsc
;
553 eh_readmem(sc
, buf
, (u_int8_t
*)hdr
, sizeof(struct dp8390_ring
));
554 #if BYTE_ORDER == BIG_ENDIAN
555 hdr
->count
= bswap16(hdr
->count
);
560 eh_test_mem(struct dp8390_softc
*dsc
)
562 struct eh_softc
*sc
= (struct eh_softc
*)dsc
;
566 mem_end
= dsc
->mem_start
+ dsc
->mem_size
;
567 memset(block
, 0, 256);
568 for (ptr
= dsc
->mem_start
; ptr
< mem_end
; ptr
+=256)
569 eh_writemem(sc
, block
, ptr
, 256);
574 * Given a NIC memory source address and a host memory destination address,
575 * copy 'amount' from NIC to host using programmed i/o. The 'amount' is
576 * rounded up to a word - ok as long as mbufs are word sized.
579 eh_readmem(struct eh_softc
*sc
, int src
, u_int8_t
*dst
, size_t amount
)
581 bus_space_tag_t nict
= sc
->sc_dp
.sc_regt
;
582 bus_space_handle_t nich
= sc
->sc_dp
.sc_regh
;
583 bus_space_tag_t datat
= sc
->sc_datat
;
584 bus_space_handle_t datah
= sc
->sc_datah
;
586 /* Select page 0 registers. */
587 NIC_BARRIER(nict
, nich
);
588 bus_space_write_1(nict
, nich
, ED_P0_CR
,
589 ED_CR_RD2
| ED_CR_PAGE_0
| ED_CR_STA
);
590 NIC_BARRIER(nict
, nich
);
592 /* Round up to a word if necessary. */
593 if ((sc
->sc_flags
& EHF_16BIT
) && (amount
& 1))
596 /* Set up DMA byte count. */
597 bus_space_write_1(nict
, nich
, ED_P0_RBCR0
, amount
);
598 bus_space_write_1(nict
, nich
, ED_P0_RBCR1
, amount
>> 8);
600 /* Set up source address in NIC mem. */
601 bus_space_write_1(nict
, nich
, ED_P0_RSAR0
, src
);
602 bus_space_write_1(nict
, nich
, ED_P0_RSAR1
, src
>> 8);
604 NIC_BARRIER(nict
, nich
);
605 bus_space_write_1(nict
, nich
, ED_P0_CR
,
606 ED_CR_RD0
| ED_CR_PAGE_0
| ED_CR_STA
);
607 NIC_BARRIER(nict
, nich
);
609 if (sc
->sc_flags
& EHF_16BIT
) {
611 if (!ALIGNED_POINTER(dst
, u_int16_t
))
614 bus_space_read_multi_stream_2(datat
, datah
, 0,
615 (u_int16_t
*)dst
, amount
>> 1);
617 bus_space_read_multi_1(datat
, datah
, 0, dst
, amount
);
621 eh_writemem(struct eh_softc
*sc
, u_int8_t
*src
, int dst
, size_t len
)
623 bus_space_tag_t nict
= sc
->sc_dp
.sc_regt
;
624 bus_space_handle_t nich
= sc
->sc_dp
.sc_regh
;
625 bus_space_tag_t datat
= sc
->sc_datat
;
626 bus_space_handle_t datah
= sc
->sc_datah
;
627 int maxwait
= 100; /* about 120us */
630 * Set-up procedure per DP83902A data sheet:
631 * I) Write a non-zero value into RBCR0.
632 * II) Set bits RD2, RD1, and RD0 to 0, 0, and 1.
633 * III) Set RBCR0, 1 and RSAR0, 1.
634 * IV) Issue the Remote Write DMA Command (RD2, RD1, RD0 = 0, 1, 0).
637 /* Select page 0 registers. */
639 NIC_BARRIER(nict
, nich
);
640 bus_space_write_1(nict
, nich
, ED_P0_CR
,
641 ED_CR_RD2
| ED_CR_PAGE_0
| ED_CR_STA
);
642 NIC_BARRIER(nict
, nich
);
644 /* Write random number. Linux writes several, follow them. */
645 bus_space_write_1(nict
, nich
, ED_P0_RBCR0
, 123);
646 bus_space_write_1(nict
, nich
, ED_P0_RBCR1
, 123);
647 bus_space_write_1(nict
, nich
, ED_P0_RSAR0
, 123);
648 bus_space_write_1(nict
, nich
, ED_P0_RSAR1
, 123);
649 NIC_BARRIER(nict
, nich
);
651 /* Select DMA read (see above) */
652 bus_space_write_1(nict
, nich
, ED_P0_CR
,
653 ED_CR_RD0
| ED_CR_PAGE_0
| ED_CR_STA
);
654 NIC_BARRIER(nict
, nich
);
656 /* Linux has a 1us pause here. Follow them. */
659 /* Reset remote DMA complete flag. */
660 bus_space_write_1(nict
, nich
, ED_P0_ISR
, ED_ISR_RDC
);
661 NIC_BARRIER(nict
, nich
);
663 /* Set up DMA byte count. */
664 bus_space_write_1(nict
, nich
, ED_P0_RBCR0
, len
);
665 bus_space_write_1(nict
, nich
, ED_P0_RBCR1
, len
>> 8);
667 /* Set up destination address in NIC mem. */
668 bus_space_write_1(nict
, nich
, ED_P0_RSAR0
, dst
);
669 bus_space_write_1(nict
, nich
, ED_P0_RSAR1
, dst
>> 8);
671 /* Set remote DMA write. */
672 NIC_BARRIER(nict
, nich
);
673 bus_space_write_1(nict
, nich
,
674 ED_P0_CR
, ED_CR_RD1
| ED_CR_PAGE_0
| ED_CR_STA
);
675 NIC_BARRIER(nict
, nich
);
677 if (sc
->sc_flags
& EHF_16BIT
) {
679 if (!ALIGNED_POINTER(dst
, u_int16_t
))
680 panic("eh_writemem");
682 bus_space_write_multi_stream_2(datat
, datah
, 0,
683 (u_int16_t
*)src
, len
>> 1);
685 bus_space_write_multi_1(datat
, datah
, 0, src
, len
);
688 * Wait for remote DMA to complete. This is necessary because on the
689 * transmit side, data is handled internally by the NIC in bursts, and
690 * we can't start another remote DMA until this one completes. Not
691 * waiting causes really bad things to happen - like the NIC wedging
694 while (((bus_space_read_1(nict
, nich
, ED_P0_ISR
) & ED_ISR_RDC
) !=
695 ED_ISR_RDC
) && --maxwait
)
699 printf("eh_writemem: failed to complete "
700 "(RSAR=0x%04x, RBCR=0x%04x, CRDA=0x%02x%02x)\n",
702 bus_space_read_1(nict
, nich
, ED_P0_CRDA1
),
703 bus_space_read_1(nict
, nich
, ED_P0_CRDA0
));
707 * Work out the media types available on the current card.
709 * We try to switch to each of 10BASE2 and 10BASE-T in turn. If the card
710 * only supports one type, the media select line will be tied to select
711 * that, so it won't move when we push it.
713 * The media select jumpers (at least on the EtherLan 100) have the same
718 eh_availmedia(struct eh_softc
*sc
)
721 /* Set the card to use AUI (10BASE2 or 10BASE-FL) */
722 bus_space_write_1(sc
->sc_ctlt
, sc
->sc_ctlh
, 0,
723 sc
->sc_ctrl
& ~EH_CTRL_MEDIA
);
724 /* Check whether that worked */
725 if ((bus_space_read_1(sc
->sc_ctl2t
, sc
->sc_ctl2h
, 0) &
726 EH_CTRL2_10B2
) == 0) {
727 bus_space_write_1(sc
->sc_ctlt
, sc
->sc_ctlh
, 0, sc
->sc_ctrl
);
731 /* Try 10BASE-T and see if that works */
732 bus_space_write_1(sc
->sc_ctlt
, sc
->sc_ctlh
, 0,
733 sc
->sc_ctrl
| EH_CTRL_MEDIA
);
734 if ((bus_space_read_1(sc
->sc_ctl2t
, sc
->sc_ctl2h
, 0) &
736 bus_space_write_1(sc
->sc_ctlt
, sc
->sc_ctlh
, 0, sc
->sc_ctrl
);
740 /* If both of them worked, this is a combo card. */
741 bus_space_write_1(sc
->sc_ctlt
, sc
->sc_ctlh
, 0, sc
->sc_ctrl
);
746 * Identify the MAU attached to an EtherLan 200-series network slot card.
748 * Follows the protocol described at the back of the Acorn A3020 and A4000
749 * Network Interface Specification.
752 eh_identifymau(struct eh_softc
*sc
)
755 bus_space_tag_t ctlt
;
756 bus_space_handle_t ctlh
;
760 /* Reset: Output 1 for a nominal 100us. */
761 /* XXX For some reason, a read is necessary between writes. */
762 bus_space_read_1(ctlt
, ctlh
, 0);
763 bus_space_write_1(ctlt
, ctlh
, 0, EH200_CTRL_MAU
);
765 for (id
= 0; id
< 128; id
++) {
766 /* Output 0 for 10us. */
767 /* XXX For some reason, a read is necessary between writes. */
768 bus_space_read_1(ctlt
, ctlh
, 0);
769 bus_space_write_1(ctlt
, ctlh
, 0, 0);
772 if (bus_space_read_1(ctlt
, ctlh
, 0) & EH200_CTRL_MAU
)
774 /* Output 1 for 10us. */
775 bus_space_write_1(ctlt
, ctlh
, 0, EH200_CTRL_MAU
);
782 eh_media_init(struct dp8390_softc
*dsc
)
784 struct eh_softc
*sc
= (struct eh_softc
*) dsc
;
787 ifmedia_init(&dsc
->sc_media
, 0, dp8390_mediachange
, dp8390_mediastatus
);
788 for (i
= 0; i
< media_switch
[sc
->sc_mediaset
].nmedia
; i
++)
789 ifmedia_add(&dsc
->sc_media
,
790 media_switch
[sc
->sc_mediaset
].media
[i
], 0, NULL
);
791 ifmedia_set(&dsc
->sc_media
, media_switch
[sc
->sc_mediaset
].media
[0]);
795 * Medium selection has changed.
798 eh_mediachange(struct dp8390_softc
*dsc
)
800 struct eh_softc
*sc
= (struct eh_softc
*)dsc
;
801 struct ifmedia
*ifm
= &dsc
->sc_media
;
803 switch (IFM_SUBTYPE(ifm
->ifm_cur
->ifm_media
)) {
805 /* Auto-media logic from Linux */
806 sc
->sc_ctrl
|= EH_CTRL_MEDIA
;
807 bus_space_write_1(sc
->sc_ctlt
, sc
->sc_ctlh
, 0, sc
->sc_ctrl
);
808 DELAY(1000); /* XXX Long enough for hub to respond? */
809 if ((bus_space_read_1(sc
->sc_ctlt
, sc
->sc_ctlh
, 0) &
810 EH_CTRL_NOLINK
) == 0)
814 sc
->sc_ctrl
&= ~EH_CTRL_MEDIA
;
815 bus_space_write_1(sc
->sc_ctlt
, sc
->sc_ctlh
, 0, sc
->sc_ctrl
);
818 sc
->sc_ctrl
|= EH_CTRL_MEDIA
;
819 bus_space_write_1(sc
->sc_ctlt
, sc
->sc_ctlh
, 0, sc
->sc_ctrl
);
823 panic("eh_mediachange");
830 * Return current medium and status.
833 eh_mediastatus(struct dp8390_softc
*dsc
, struct ifmediareq
*ifmr
)
835 struct eh_softc
*sc
= (struct eh_softc
*)dsc
;
838 /* XXX 10BASE-FL on E513? */
839 /* Read the actual medium currently in use. */
840 ctrl2
= bus_space_read_1(sc
->sc_ctl2t
, sc
->sc_ctl2h
, 0);
841 if (ctrl2
& EH_CTRL2_10B2
) {
842 ifmr
->ifm_active
= IFM_ETHER
| IFM_10_2
;
844 ifmr
->ifm_active
= IFM_ETHER
| IFM_10_T
;
845 ifmr
->ifm_status
= IFM_AVALID
;
846 if ((bus_space_read_1(sc
->sc_ctlt
, sc
->sc_ctlh
, 0) &
847 EH_CTRL_NOLINK
) == 0)
848 ifmr
->ifm_status
|= IFM_ACTIVE
;