1 /* $NetBSD: if_ne_pbus.c,v 1.14 2008/03/12 14:31:11 cube Exp $ */
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Mark Brinicombe of Causality Limited.
10 * EtherH code Copyright (c) 1998 Mike Pumford
11 * EtherN/EtherI code Copyright (c) 1999 Mike Pumford
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
36 * This driver uses the generic ne2000 & dp8390 IC drivers
39 * ANT EtherM network slot cards
40 * ICubed Etherlan 600 (EtherH) network slot cards
41 * Irlam EtherN podules
42 * Acorn EtherI podules (identical hardware to EtherN)
44 * Thanks go to Stephen Borrill for providing the EtherN card
45 * and information to program it.
47 * TO DO List for this Driver.
49 * EtherM - Needs proper media support.
52 #include <sys/cdefs.h>
53 __KERNEL_RCSID(0, "$NetBSD: if_ne_pbus.c,v 1.14 2008/03/12 14:31:11 cube Exp $");
55 #include <sys/param.h>
56 #include <sys/device.h>
57 #include <sys/socket.h>
58 #include <sys/systm.h>
62 #include <net/if_dl.h>
63 #include <net/if_ether.h>
64 #include <net/if_media.h>
66 #include <machine/bus.h>
67 #include <machine/intr.h>
68 #include <machine/io.h>
69 #include <dev/ic/dp8390reg.h>
70 #include <dev/ic/dp8390var.h>
71 #include <dev/ic/ne2000reg.h>
72 #include <dev/ic/ne2000var.h>
73 #include <dev/ic/dp83905reg.h>
74 #include <dev/ic/dp83905var.h>
75 #include <dev/ic/mx98905var.h>
77 #include <arch/acorn32/podulebus/podulebus.h>
78 #include <arch/acorn32/podulebus/if_ne_pbusreg.h>
80 #include <dev/podulebus/podules.h>
83 * ne_pbus_softc: ne2000_softc plus podule, interrupt and bs tag info
85 struct ne_pbus_softc
{
86 struct ne2000_softc sc_ne2000
; /* ne2000 softc */
89 struct bus_space sc_tag
; /* Patched tag */
90 irqhandler_t
*sc_ih
; /* Interrupt handler */
91 struct evcnt sc_intrcnt
; /* Interrupt count */
92 bus_space_handle_t sc_extrah
; /* Bus handle for any
97 * Attach data and prototypes for driver
99 static int ne_pbus_probe (device_t
, cfdata_t
, void *);
100 static void ne_pbus_attach (device_t
, device_t
, void *);
102 CFATTACH_DECL_NEW(ne_pbus
, sizeof(struct ne_pbus_softc
),
103 ne_pbus_probe
, ne_pbus_attach
, NULL
, NULL
);
106 * Prototypes for interface specific routines
108 static u_int8_t
*em_ea (struct ne_pbus_softc
*sc
, u_int8_t
*buffer
);
109 static void em_postattach (struct ne_pbus_softc
*sc
);
110 static void eh600_postattach (struct ne_pbus_softc
*sc
);
111 static void eh600_preattach (struct ne_pbus_softc
*sc
);
112 static u_int8_t
*eh600_ea (struct ne_pbus_softc
*sc
, u_int8_t
*buffer
);
114 void eh600_init_media (struct dp8390_softc
*);
116 void en_postattach (struct ne_pbus_softc
*);
117 void en_init_media (struct dp8390_softc
*);
120 * Define a structure to hold all the information required on an NE2000
122 * We create an array of these structures to describe all the interfaces
123 * that we can handle via the MI NE2000 driver.
126 int product
; /* podule product id */
127 unsigned int cookie
; /* podulebus space cookie */
128 unsigned int nicbase
; /* byte offset of NIC */
129 unsigned int nicsize
; /* size of NIC (regs) */
130 unsigned int asicbase
; /* byte offset of ASIC */
131 unsigned int asicsize
; /* size of ASIC (regs) */
132 unsigned int extrabase
; /* extra registers byte offset */
133 unsigned int extrasize
; /* size of extra registers(regs) */
134 unsigned char nicspace
; /* easi,fast or mod space ? */
135 unsigned char asicspace
; /* easi,fast or mod space ? */
136 unsigned char extraspace
; /* easi,fast or mod space ? */
137 #define NE_SPACE_FAST 0
138 #define NE_SPACE_MOD 1
139 #define NE_SPACE_EASI 2
140 unsigned char reserved0
; /* not used (padding) */
141 const char *name
; /* name */
142 u_int8_t
* (*getea
) /* do this to get the MAC */
143 (struct ne_pbus_softc
*sc
, u_int8_t
*buffer
);
144 void (*preattach
) /* do this before attach */
145 (struct ne_pbus_softc
*sc
);
146 void (*postattach
) /* do this after attach */
147 (struct ne_pbus_softc
*sc
);
148 int (*mediachange
) /* media change */
149 (struct dp8390_softc
*);
150 void (*mediastatus
) /* media status */
151 (struct dp8390_softc
*, struct ifmediareq
*);
152 void (*init_card
) /* media init card */
153 (struct dp8390_softc
*);
154 void (*init_media
) /* media init */
155 (struct dp8390_softc
*);
157 /* ANT EtherM netslot interface */
159 PODULE_ETHERM
, EM_REGSHIFT
,
160 EM_NIC_OFFSET
, EM_NIC_SIZE
, EM_ASIC_OFFSET
, EM_ASIC_SIZE
,
162 NE_SPACE_FAST
, NE_SPACE_FAST
, 0,
163 "EtherM", em_ea
, NULL
, em_postattach
,
166 /* ICubed EtherLan EtherH netslot interface */
168 PODULE_ETHERLAN600
, EH600_REGSHIFT
,
169 EH600_NIC_OFFSET
, EH600_NIC_SIZE
, EH600_ASIC_OFFSET
, EH600_ASIC_SIZE
,
170 EH600_CONTROL_OFFSET
, EH600_CONTROL_SIZE
, NE_SPACE_FAST
,
171 NE_SPACE_FAST
, NE_SPACE_FAST
, 0,
172 "EtherLan 600", eh600_ea
, eh600_preattach
, eh600_postattach
,
173 dp83905_mediachange
, dp83905_mediastatus
, dp83905_init_card
,
176 /* Acorn EtherLan EtherH netslot interface */
178 PODULE_ETHERLAN600AEH
, EH600_REGSHIFT
,
179 EH600_NIC_OFFSET
, EH600_NIC_SIZE
, EH600_ASIC_OFFSET
, EH600_ASIC_SIZE
,
180 EH600_CONTROL_OFFSET
, EH600_CONTROL_SIZE
, NE_SPACE_FAST
,
181 NE_SPACE_FAST
, NE_SPACE_FAST
, 0,
182 "EtherLan 600A", eh600_ea
, eh600_preattach
, eh600_postattach
,
183 dp83905_mediachange
, dp83905_mediastatus
, dp83905_init_card
,
186 /* Irlam EtherN podule. (supplied with NC) */
188 PODULE_ETHERN
, EN_REGSHIFT
,
189 EN_NIC_OFFSET
, EN_NIC_SIZE
, EN_ASIC_OFFSET
, EN_ASIC_SIZE
,
191 NE_SPACE_EASI
, NE_SPACE_EASI
, 0,
192 "EtherN", em_ea
, NULL
, en_postattach
,
193 dp83905_mediachange
, dp83905_mediastatus
, dp83905_init_card
,
196 /* Acorn EtherI podule. (supplied with NC) */
198 PODULE_ETHERI
, EN_REGSHIFT
,
199 EN_NIC_OFFSET
, EN_NIC_SIZE
, EN_ASIC_OFFSET
, EN_ASIC_SIZE
,
201 NE_SPACE_EASI
, NE_SPACE_EASI
, 0,
202 "EtherI", em_ea
, NULL
, en_postattach
,
203 dp83905_mediachange
, dp83905_mediastatus
, dp83905_init_card
,
209 * Determine if the device is present.
212 ne_pbus_probe(device_t parent
, cfdata_t cf
, void *aux
)
214 struct podule_attach_args
*pa
= (void *) aux
;
217 /* Scan the list of known interfaces looking for a match */
218 for (loop
= 0; loop
< sizeof(ne_clones
) / sizeof(struct ne_clone
);
220 if (pa
->pa_product
== ne_clones
[loop
].product
)
227 * Install interface into kernel networking data structures.
230 ne_pbus_attach(device_t parent
, device_t self
, void *aux
)
232 struct podule_attach_args
*pa
= (void *)aux
;
233 struct ne_pbus_softc
*npsc
= device_private(self
);
234 struct ne2000_softc
*nsc
= &npsc
->sc_ne2000
;
235 struct dp8390_softc
*dsc
= &nsc
->sc_dp8390
;
237 int *media
, nmedia
, defmedia
;
238 struct ne_clone
*ne
= NULL
;
245 nmedia
= defmedia
= 0;
246 /* Check a few things about the attach args */
248 if (pa
->pa_podule_number
== -1)
249 panic("Podule has disappeared !");
251 npsc
->sc_podule_number
= pa
->pa_podule_number
;
252 npsc
->sc_podule
= pa
->pa_podule
;
253 podules
[npsc
->sc_podule_number
].attached
= 1; /* XXX */
255 /* Scan the list of known interfaces for a match */
256 for (loop
= 0; loop
< sizeof(ne_clones
) / sizeof(struct ne_clone
);
258 if (pa
->pa_product
== ne_clones
[loop
].product
) {
259 ne
= &ne_clones
[loop
];
265 /* This should never fail as we must have matched at probe time */
267 panic("Podule has vanished");
270 /* Update the nic and asic base addresses appropriately */
271 switch (ne
->nicspace
) {
273 ne
->nicbase
+= npsc
->sc_podule
->easi_base
;
276 ne
->nicbase
+= npsc
->sc_podule
->mod_base
;
280 ne
->nicbase
+= npsc
->sc_podule
->fast_base
;
283 switch (ne
->asicspace
) {
285 ne
->asicbase
+= npsc
->sc_podule
->easi_base
;
288 ne
->asicbase
+= npsc
->sc_podule
->mod_base
;
292 ne
->asicbase
+= npsc
->sc_podule
->fast_base
;
296 switch (ne
->extraspace
) {
298 ne
->extrabase
+= npsc
->sc_podule
->easi_base
;
301 ne
->extrabase
+= npsc
->sc_podule
->mod_base
;
305 ne
->extrabase
+= npsc
->sc_podule
->fast_base
;
309 /* Report the interface name */
310 aprint_normal(": %s ethernet\n", ne
->name
);
313 * Ok we need our own bus tag as the register spacing
314 * may not the default.
316 * For the podulebus, the bus tag cookie is the shift
317 * to apply to registers
318 * So duplicate the bus space tag and change the
322 npsc
->sc_tag
= *pa
->pa_iot
;
323 npsc
->sc_tag
.bs_cookie
= (void *) ne
->cookie
;
325 dsc
->sc_regt
= &npsc
->sc_tag
;
326 nsc
->sc_asict
= dsc
->sc_regt
;
328 /* Map all the I/O space for the NIC */
329 if (bus_space_map(dsc
->sc_regt
, ne
->nicbase
, ne
->nicsize
,
331 aprint_error_dev(self
, "cannot map i/o space\n");
334 /* Map the I/O space for the ASIC */
335 if (bus_space_map(nsc
->sc_asict
, ne
->asicbase
, ne
->asicsize
,
336 0, &nsc
->sc_asich
)) {
337 aprint_error_dev(self
, "cannot map i/o space\n");
340 /* Map any extra register space required by the card */
341 if (ne
->extrasize
> 0) {
342 if (bus_space_map(&npsc
->sc_tag
, ne
->extrabase
, ne
->extrasize
,
343 0, &npsc
->sc_extrah
)) {
344 aprint_error_dev(self
, "cannot map extra space\n");
349 /* This interface is always enabled. */
353 * Now get the ethernet address in an interface specific manner if
357 myea
= ne
->getea(npsc
, buffer
);
361 /* Does the interface need a preattach call ? */
365 /* if the interface has media support initialise it */
366 if (ne
->init_media
) {
367 dsc
->sc_mediachange
= ne
->mediachange
;
368 dsc
->sc_mediastatus
= ne
->mediastatus
;
369 dsc
->init_card
= ne
->init_card
;
370 dsc
->sc_media_init
= ne
->init_media
;
371 /* ne->init_media(dsc,&media,&nmedia,&defmedia); */
375 * Do generic NE2000 attach. This will read the station address
378 ne2000_attach(nsc
, myea
);
379 aprint_normal_dev(self
, "");
380 switch (nsc
->sc_type
) {
381 case NE2000_TYPE_NE1000
:
382 aprint_normal("NE1000");
384 case NE2000_TYPE_NE2000
:
385 aprint_normal("NE2000");
387 case NE2000_TYPE_AX88190
:
388 aprint_normal("AX88190");
390 case NE2000_TYPE_DL10019
:
391 aprint_normal("DL10019");
393 case NE2000_TYPE_DL10022
:
394 aprint_normal("DL10022");
399 aprint_normal(" chipset, %d Kb memory\n", dsc
->mem_start
/1024);
401 /* Does the interface need a postattach call ? */
403 ne
->postattach(npsc
);
405 /* Install an interrupt handler */
406 evcnt_attach_dynamic(&npsc
->sc_intrcnt
, EVCNT_TYPE_INTR
, NULL
,
407 device_xname(self
), "intr");
408 npsc
->sc_ih
= podulebus_irq_establish(pa
->pa_ih
, IPL_NET
, dp8390_intr
,
409 dsc
, &npsc
->sc_intrcnt
);
410 if (npsc
->sc_ih
== NULL
)
411 panic("%s: Cannot install interrupt handler",
413 /* this feels wrong to do this here */
414 npsc
->sc_ih
->ih_maskaddr
= npsc
->sc_podule
->irq_addr
;
415 npsc
->sc_ih
->ih_maskbits
= npsc
->sc_podule
->irq_mask
;
421 * return the ethernet address for an EtherM netslot interface.
422 * The EtherM interface uses the machines ethernet address so just
426 em_ea(struct ne_pbus_softc
*sc
, uint8_t *buffer
)
429 * Use the podulebus netslot_ea() function to get the netslot
430 * ethernet address. This is generated from the machine ID.
440 * The EtherM interface has a Diagnostic Status register. After attaching
441 * the driver, print out some more information using this register.
444 em_postattach(struct ne_pbus_softc
*sc
)
449 * Report information from the Diagnostic Status Register for
452 aprint_normal_dev(sc
->sc_ne2000
.sc_dp8390
.sc_dev
,
453 "16KB buffer memory");
455 /* Get the Diagnostic Status Register */
456 dsr
= bus_space_read_1(sc
->sc_ne2000
.sc_asict
,
457 sc
->sc_ne2000
.sc_asich
, EM_DSR_REG
);
459 /* Check for bits that indicate a fault */
460 if (!(dsr
& EM_DSR_20M
))
461 aprint_normal(", VCO faulty");
462 if (!(dsr
& EM_DSR_TCOK
))
463 aprint_normal(", TxClk faulty");
465 /* Report status of card */
466 if (dsr
& EM_DSR_POL
)
467 aprint_normal(", UTP reverse polarity");
468 if (dsr
& EM_DSR_JAB
)
469 aprint_normal(", jabber");
470 if (dsr
& EM_DSR_LNK
)
471 aprint_normal(", link OK");
472 if (dsr
& EM_DSR_LBK
)
473 aprint_normal(", loopback");
474 if (dsr
& EM_DSR_UTP
)
475 aprint_normal(", UTP");
483 * pre-initialise the AT/Lantic chipset so that the card probes and
487 eh600_preattach(struct ne_pbus_softc
*sc
)
490 struct ne2000_softc
*nsc
= &sc
->sc_ne2000
;
491 struct dp8390_softc
*dsc
= &nsc
->sc_dp8390
;
492 bus_space_tag_t nict
= dsc
->sc_regt
;
493 bus_space_handle_t nich
= dsc
->sc_regh
;
495 /* initialise EH600 config register */
496 bus_space_read_1(nict
, nich
, DP83905_MCRA
);
497 bus_space_write_1(nict
, nich
, DP83905_MCRA
, DP83905_MCRA_INT3
);
499 /* enable interrupts for the card */
500 tmp
= bus_space_read_1(&sc
->sc_tag
,sc
->sc_extrah
,0);
502 bus_space_write_1(&sc
->sc_tag
,sc
->sc_extrah
,0,tmp
);
508 * Etherlan 600 has 32k of buffer memory as it runs the AT/Lantic
509 * DP8390 clone in IO non-compatible mode. We need to adjust the memory
510 * description set up by dp8390.c and ne2000.c to reflect this.
513 eh600_postattach(struct ne_pbus_softc
*sc
)
515 struct ne2000_softc
*nsc
= &sc
->sc_ne2000
;
516 struct dp8390_softc
*dsc
= &nsc
->sc_dp8390
;
517 /* first page is mapped to the PROM. so start at 2nd page */
518 dsc
->mem_start
= EH600_MEM_START
;
519 dsc
->mem_size
= EH600_MEM_END
- EH600_MEM_START
;
520 dsc
->mem_end
= EH600_MEM_END
;
521 dsc
->txb_cnt
= 3; /* >16k of ram setup 3 tx buffers */
522 /* recompute the mem ring (taken straight from the ne2000 init code) */
525 (((dsc
->txb_cnt
+ 1) * ED_TXBUF_SIZE
) <<
528 /* recompute the dp8390 register values. (from dp8390 init code) */
529 dsc
->tx_page_start
= dsc
->mem_start
>> ED_PAGE_SHIFT
;
531 dsc
->rec_page_start
= dsc
->tx_page_start
+
532 (dsc
->txb_cnt
+ 1) * ED_TXBUF_SIZE
;
534 dsc
->rec_page_stop
= dsc
->tx_page_start
+
535 (dsc
->mem_size
>> ED_PAGE_SHIFT
);
536 aprint_normal_dev(dsc
->sc_dev
, "32KB buffer memory\n");
539 * EtherLan 600 media.
541 void eh600_init_media(struct dp8390_softc
*sc
)
543 static int eh600_media
[] = {
548 int i
, defmedia
= IFM_ETHER
|IFM_AUTO
;
549 static const int eh600_nmedia
=
550 sizeof(eh600_media
) / sizeof(eh600_media
[0]);
552 aprint_normal_dev(sc
->sc_dev
,
553 "10base2, 10baseT, auto, default auto\n");
555 ifmedia_init(&sc
->sc_media
, 0, dp8390_mediachange
, dp8390_mediastatus
);
556 for (i
= 0; i
< eh600_nmedia
; i
++)
557 ifmedia_add(&sc
->sc_media
, eh600_media
[i
], 0, NULL
);
558 ifmedia_set(&sc
->sc_media
, defmedia
);
564 en_postattach(struct ne_pbus_softc
*sc
)
567 mx98905_attach(&sc
->sc_ne2000
.sc_dp8390
);
574 en_init_media(struct dp8390_softc
*sc
)
576 static int en_media
[] = {
579 aprint_normal_dev(sc
->sc_dev
, "10baseT, default 10baseT\n");
581 ifmedia_init(&sc
->sc_media
, 0, dp8390_mediachange
, dp8390_mediastatus
);
582 ifmedia_add(&sc
->sc_media
, en_media
[0], 0, NULL
);
583 ifmedia_set(&sc
->sc_media
, en_media
[0]);
588 * extracts the station address from the Podule description string.
589 * The description has to be re-read here since the podule description
590 * string is not always long enough to contain the full address.
592 * If for any reason we cannot extract the address this routine will
593 * use netslot_ea() to return the generic address for the network slot.
596 #define POD_READ(addr) \
597 podule->read_rom(podule->sync_base, addr)
600 eh600_ea(struct ne_pbus_softc
*sc
, uint8_t *buffer
)
602 podule_t
*podule
= sc
->sc_podule
;
607 memset(buffer
, 0, 6);
609 /* read chunks from the podule */
611 id
= POD_READ(address
);
612 /* check for description chunk. */
619 size
= POD_READ(address
+ 4);
620 size
|= (POD_READ(address
+ 8) << 8);
621 size
|= (POD_READ(address
+ 12) << 16);
623 /* read address of description */
624 pod_addr
= POD_READ(address
+ 16);
625 pod_addr
|= (POD_READ(address
+ 20) << 8);
626 pod_addr
|= (POD_READ(address
+ 24) << 16);
627 pod_addr
|= (POD_READ(address
+ 28) << 24);
629 if (pod_addr
< 0x800) {
635 * start scanning for ethernet address
636 * which starts with a '('
638 for (loop
= 0; loop
< size
; ++loop
) {
640 /* we have found a '(' so start decoding the address */
641 tmp
= POD_READ((pod_addr
+ loop
) * 4);
642 if (tmp
>= '0' && tmp
<= '9') {
643 buffer
[addr_index
>> 1] |= (tmp
- '0') << ((addr_index
& 1) ? 0 : 4);
646 else if (tmp
>= 'a' && tmp
<= 'f'){
647 buffer
[addr_index
>> 1] |= (10 + (tmp
- 'a')) << ((addr_index
& 1) ? 0 : 4);
650 else if (tmp
>= 'A' && tmp
<= 'F'){
651 buffer
[addr_index
>> 1] |= (10 + (tmp
- 'A')) << ((addr_index
& 1) ? 0 : 4);
654 else if (tmp
== ')') {
655 /* we have read the whole address so we can stop scanning
656 * the podule description */
661 * we have found the start of the ethernet address (decode begins
662 * on the next run round the loop. */
663 if (POD_READ((pod_addr
+ loop
) * 4) == '(') {
668 * Failed to find the address so fall back
669 * on the netslot address
677 } while (id
!= 0 && address
< 0x8000);
680 * If we get here we failed to find the address
681 * In this case the best solution is to go with the netslot addrness