Sync usage with man page.
[netbsd-mini2440.git] / sys / arch / acorn26 / podulebus / if_eh.c
blob3351cae741b84ebb64c583d7a443de3780355a3c
1 /* $NetBSD: if_eh.c,v 1.14 2008/04/28 20:23:09 martin Exp $ */
3 /*-
4 * Copyright (c) 2000 Ben Harris
5 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
6 * All rights reserved.
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
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.
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>
53 #include <sys/mbuf.h>
54 #include <sys/reboot.h>
55 #include <sys/syslog.h>
57 #include <net/if.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>
81 #define EH_MEDIA_2 0
82 #define EH_MEDIA_T 1
83 #define EH_MEDIA_2_T 2
84 #define EH_MEDIA_FL_T 3
86 struct eh_softc {
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;
94 void *sc_ih;
95 struct evcnt sc_intrcnt;
96 int sc_flags;
97 #define EHF_16BIT 0x01
98 #define EHF_MAU 0x02
99 int sc_type;
100 int sc_mediaset;
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 *);
117 /* if_media glue */
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);
128 static int
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:
140 return 1;
142 return 0;
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 {
151 int nmedia;
152 int *media;
153 } media_switch[] = {
154 { 1, media_only2 },
155 { 1, media_onlyt },
156 { 3, media_2andt }
159 static void
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;
166 int i;
167 char *ptr;
168 u_int8_t *myaddr;
170 dsc->sc_dev = self;
172 /* Canonicalise card type. */
173 switch (pa->pa_product) {
174 case PODULE_ETHERLAN100:
175 case PODULE_ETHERLAN100AEH:
176 sc->sc_type = PODULE_ETHERLAN100;
177 break;
178 case PODULE_ETHERLAN200:
179 case PODULE_ETHERLAN200AEH:
180 sc->sc_type = PODULE_ETHERLAN200;
181 break;
182 case PODULE_ETHERLAN500:
183 case PODULE_ETHERLAN500AEH:
184 sc->sc_type = PODULE_ETHERLAN500;
185 break;
188 /* Memory size and width varies. */
189 dsc->mem_start = 0;
190 switch (sc->sc_type) {
191 case PODULE_ETHERLAN200:
192 sc->sc_flags |= EHF_MAU;
193 /* FALLTHROUGH */
194 case PODULE_ETHERLAN100:
195 printf(": 8-bit, 32 KB RAM");
196 dsc->mem_size = 0x8000;
197 break;
198 case PODULE_ETHERLAN500:
199 printf(": 16-bit, 64 KB RAM");
200 sc->sc_flags |= EHF_16BIT;
201 dsc->mem_size = 0x10000;
202 break;
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,
208 &dsc->sc_regh);
209 sc->sc_datat = pa->pa_mod_t;
210 bus_space_subregion(sc->sc_datat, pa->pa_mod_h, EH_DATA, 1,
211 &sc->sc_datah);
212 sc->sc_ctlt = pa->pa_fast_t;
213 bus_space_subregion(sc->sc_ctlt, pa->pa_fast_h, EH_CTRL, 1,
214 &sc->sc_ctlh);
215 sc->sc_ctl2t = pa->pa_fast_t;
216 bus_space_subregion(sc->sc_ctl2t, pa->pa_fast_h, EH_CTRL2, 1,
217 &sc->sc_ctl2h);
219 /* dsc->cr_proto? */
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;
231 /* dsc->recv_int */
232 dsc->ring_copy = eh_ring_copy;
233 dsc->write_mbuf = eh_write_mbuf;
234 /* dsc->sc_enable */
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;
244 sc->sc_ctrl = 0x00;
246 if (sc->sc_flags & EHF_MAU) {
247 mautype = eh_identifymau(sc);
248 switch (mautype) {
249 case EH200_MAUID_10_2:
250 printf(", 10BASE2 MAU");
251 mediaset = EH_MEDIA_2;
252 break;
253 case EH200_MAUID_10_T:
254 printf(", 10BASE-T MAU");
255 mediaset = EH_MEDIA_T;
256 break;
257 default:
258 printf(", unknown MAU id %d", mautype);
259 mediaset = EH_MEDIA_2; /* XXX */
260 break;
262 } else {
263 mediaset = eh_availmedia(sc);
264 switch (mediaset) {
265 case EH_MEDIA_2:
266 printf(", 10BASE2 only");
267 break;
268 case EH_MEDIA_T:
269 printf(", 10BASE-T only");
270 break;
271 case EH_MEDIA_2_T:
272 printf(", combo 10BASE2/-T");
273 break;
276 sc->sc_mediaset = mediaset;
277 printf("\n");
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");
289 return;
291 ptr = strchr(pa->pa_descr, '(');
292 if (ptr == NULL) {
293 printf(": Ethernet address not found in description\n");
294 return;
296 ptr++;
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 "
301 "description\n");
302 return;
306 dp8390_config(dsc);
307 dp8390_stop(dsc);
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);
313 if (bootverbose)
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);
320 static void
321 eh_init_card(struct dp8390_softc *sc)
324 eh_mediachange(sc);
328 * Write an mbuf chain to the destination NIC memory address using programmed
329 * I/O.
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;
339 int savelen, padlen;
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;
346 } else
347 padlen = 0;
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. */
372 DELAY(1);
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
401 * mbufs.
403 if ((sc->sc_flags & EHF_16BIT) == 0) {
404 /* NE1000s are easy. */
405 for (; m != 0; m = m->m_next)
406 if (m->m_len)
407 bus_space_write_multi_1(datat, datah, 0,
408 mtod(m, u_int8_t *), m->m_len);
409 if (padlen) {
410 for(; padlen > 0; padlen--)
411 bus_space_write_1(datat, datah, 0, 0);
413 } else {
414 /* NE2000s are a bit trickier. */
415 u_int8_t *data, savebyte[2];
416 int l, leftover;
417 #ifdef DIAGNOSTIC
418 u_int8_t *lim;
419 #endif
420 /* Start out with no leftover data. */
421 leftover = 0;
422 savebyte[0] = savebyte[1] = 0;
424 for (; m != 0; m = m->m_next) {
425 l = m->m_len;
426 if (l == 0)
427 continue;
428 data = mtod(m, u_int8_t *);
429 #ifdef DIAGNOSTIC
430 lim = data + l;
431 #endif
432 while (l > 0) {
433 if (leftover) {
435 * Data left over (from mbuf or
436 * realignment). Buffer the next
437 * byte, and write it and the
438 * leftover data out.
440 savebyte[1] = *data++;
441 l--;
442 bus_space_write_stream_2(datat, datah,
444 *(u_int16_t *)savebyte);
445 leftover = 0;
446 } else if (BUS_SPACE_ALIGNED_POINTER(data,
447 u_int16_t) == 0) {
449 * Unaligned data; buffer the next
450 * byte.
452 savebyte[0] = *data++;
453 l--;
454 leftover = 1;
455 } else {
457 * Aligned data; output contiguous
458 * words as much as we can, then
459 * buffer the remaining byte, if any.
461 leftover = l & 1;
462 l &= ~1;
463 bus_space_write_multi_stream_2(datat,
464 datah, 0,
465 (u_int16_t *)data, l >> 1);
466 data += l;
467 if (leftover)
468 savebyte[0] = *data++;
469 l = 0;
472 if (l < 0)
473 panic("eh_write_mbuf: negative len");
474 #ifdef DIAGNOSTIC
475 if (data != lim)
476 panic("eh_write_mbuf: data != lim");
477 #endif
479 if (leftover) {
480 savebyte[1] = 0;
481 bus_space_write_stream_2(datat, datah, 0,
482 *(u_int16_t *)savebyte);
484 if (padlen) {
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
496 * the bus.
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);
503 DELAY(1);
506 if (maxwait == 0) {
507 log(LOG_WARNING,
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));
513 dp8390_reset(dsc);
516 return (savelen);
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
522 * ring-wrap.
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;
528 u_short tmp_amount;
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;
539 src = dsc->mem_ring;
540 dst += tmp_amount;
543 eh_readmem(sc, src, dst, amount);
545 return (src + amount);
548 void
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);
556 #endif
560 eh_test_mem(struct dp8390_softc *dsc)
562 struct eh_softc *sc = (struct eh_softc *)dsc;
563 u_int8_t block[256];
564 int ptr, mem_end;
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);
570 return 0;
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.
578 void
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))
594 ++amount;
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) {
610 #ifdef DIAGNOSTIC
611 if (!ALIGNED_POINTER(dst, u_int16_t))
612 panic("eh_readmem");
613 #endif
614 bus_space_read_multi_stream_2(datat, datah, 0,
615 (u_int16_t *)dst, amount >> 1);
616 } else
617 bus_space_read_multi_1(datat, datah, 0, dst, amount);
620 void
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. */
657 DELAY(1);
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) {
678 #ifdef DIAGNOSTIC
679 if (!ALIGNED_POINTER(dst, u_int16_t))
680 panic("eh_writemem");
681 #endif
682 bus_space_write_multi_stream_2(datat, datah, 0,
683 (u_int16_t *)src, len >> 1);
684 } else
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
692 * the bus.
694 while (((bus_space_read_1(nict, nich, ED_P0_ISR) & ED_ISR_RDC) !=
695 ED_ISR_RDC) && --maxwait)
696 DELAY(1);
698 if (maxwait == 0)
699 printf("eh_writemem: failed to complete "
700 "(RSAR=0x%04x, RBCR=0x%04x, CRDA=0x%02x%02x)\n",
701 dst, (u_int)len,
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
714 * effect.
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);
728 return EH_MEDIA_T;
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) &
735 EH_CTRL2_10B2)) {
736 bus_space_write_1(sc->sc_ctlt, sc->sc_ctlh, 0, sc->sc_ctrl);
737 return EH_MEDIA_2;
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);
742 return EH_MEDIA_2_T;
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)
754 int id;
755 bus_space_tag_t ctlt;
756 bus_space_handle_t ctlh;
758 ctlt = sc->sc_ctlt;
759 ctlh = sc->sc_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);
764 DELAY(200000);
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);
770 DELAY(10);
771 /* Read state. */
772 if (bus_space_read_1(ctlt, ctlh, 0) & EH200_CTRL_MAU)
773 break;
774 /* Output 1 for 10us. */
775 bus_space_write_1(ctlt, ctlh, 0, EH200_CTRL_MAU);
776 DELAY(10);
778 return id;
781 void
782 eh_media_init(struct dp8390_softc *dsc)
784 struct eh_softc *sc = (struct eh_softc *) dsc;
785 int i;
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)) {
804 case IFM_AUTO:
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)
811 break;
812 /* FALLTHROUGH */
813 case IFM_10_2:
814 sc->sc_ctrl &= ~EH_CTRL_MEDIA;
815 bus_space_write_1(sc->sc_ctlt, sc->sc_ctlh, 0, sc->sc_ctrl);
816 break;
817 case IFM_10_T:
818 sc->sc_ctrl |= EH_CTRL_MEDIA;
819 bus_space_write_1(sc->sc_ctlt, sc->sc_ctlh, 0, sc->sc_ctrl);
820 break;
821 #ifdef DIAGNOSTIC
822 default:
823 panic("eh_mediachange");
824 #endif
826 return 0;
830 * Return current medium and status.
832 void
833 eh_mediastatus(struct dp8390_softc *dsc, struct ifmediareq *ifmr)
835 struct eh_softc *sc = (struct eh_softc *)dsc;
836 int ctrl2;
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;
843 } else {
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;