1 /* $NetBSD: if_we_mca.c,v 1.20 2008/03/12 14:31:11 cube Exp $ */
4 * Copyright (c) 1997, 1998, 2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center, and Jaromir Dolecek.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
37 * Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
39 * Copyright (C) 1993, David Greenman. This software may be used, modified,
40 * copied, distributed, and sold, in both source and binary form provided that
41 * the above copyright and these terms are retained. Under no circumstances is
42 * the author responsible for the proper functioning of this software, nor does
43 * the author assume any responsibility for damages incurred with its use.
47 * Device driver for the Western Digital/SMC 8003 and 8013 series,
48 * and the SMC Elite Ultra (8216).
50 * Currently only tested with WD8003W/A and EtherCard PLUS Elite 10T/A
51 * (8013WP/A). Other WD8003 and SMC Elite based cards should work
52 * without problems too.
55 #include <sys/cdefs.h>
56 __KERNEL_RCSID(0, "$NetBSD: if_we_mca.c,v 1.20 2008/03/12 14:31:11 cube Exp $");
58 #include <sys/param.h>
59 #include <sys/systm.h>
60 #include <sys/device.h>
61 #include <sys/socket.h>
65 #include <net/if_types.h>
66 #include <net/if_media.h>
67 #include <net/if_ether.h>
71 #include <dev/mca/mcareg.h>
72 #include <dev/mca/mcavar.h>
73 #include <dev/mca/mcadevs.h>
75 #include <dev/ic/dp8390reg.h>
76 #include <dev/ic/dp8390var.h>
77 #include <dev/ic/wereg.h>
78 #include <dev/ic/wevar.h>
83 int we_mca_probe(device_t
, cfdata_t
, void *);
84 void we_mca_attach(device_t
, device_t
, void *);
85 void we_mca_init_hook(struct we_softc
*);
87 CFATTACH_DECL_NEW(we_mca
, sizeof(struct we_softc
),
88 we_mca_probe
, we_mca_attach
, NULL
, NULL
);
91 * The types for some cards may not be correct; hopefully it's close
94 static const struct we_mca_product
{
99 const char *we_typestr
;
100 } we_mca_products
[] = {
101 { MCA_PRODUCT_WD_8013EP
, "EtherCard PLUS Elite/A (8013EP/A)",
102 WD_ELITE
, WE_TYPE_WD8013EP
, "WD8013EP/A" },
103 { MCA_PRODUCT_WD_8013WP
, "EtherCard PLUS Elite 10T/A (8013WP/A)",
104 WD_ELITE
, WE_TYPE_WD8013EP
, "WD8013WP/A" },
105 { MCA_PRODUCT_IBM_WD_2
,"IBM PS/2 Adapter/A for Ethernet Networks (UTP)",
106 WD_ELITE
, WE_TYPE_WD8013EP
, "WD8013WP/A"},
107 { MCA_PRODUCT_IBM_WD_T
,"IBM PS/2 Adapter/A for Ethernet Networks (BNC)",
108 WD_ELITE
, WE_TYPE_WD8013EP
, "WD8013WP/A"},
109 { MCA_PRODUCT_WD_8003E
, "WD EtherCard PLUS/A (WD8003E/A or WD8003ET/A)",
110 WD_8003
, WE_TYPE_WD8003E
, "WD8003E/A or WD8003ET/A" },
111 { MCA_PRODUCT_WD_8003ST
,"WD StarCard PLUS/A (WD8003ST/A)",
112 WD_8003
, WE_TYPE_WD8003W
, "WD8003ST/A" }, /* XXX */
113 { MCA_PRODUCT_WD_8003W
, "WD EtherCard PLUS 10T/A (WD8003W/A)",
114 WD_8003
, WE_TYPE_WD8003W
, "WD8003W/A" },
115 { MCA_PRODUCT_IBM_WD_O
, "IBM PS/2 Adapter/A for Ethernet Networks",
116 WD_8003
, WE_TYPE_WD8003W
, "IBM PS/2 Adapter/A" },
121 /* see POS description in we_mca_attach() */
122 static const int we_mca_irq
[] = {
126 static const struct we_mca_product
*we_mca_lookup(int);
128 static const struct we_mca_product
*
129 we_mca_lookup(int id
)
131 const struct we_mca_product
*wep
;
133 for(wep
= we_mca_products
; wep
->we_name
; wep
++)
134 if (wep
->we_id
== id
)
141 we_mca_probe(device_t parent
, cfdata_t cf
, void *aux
)
143 struct mca_attach_args
*ma
= aux
;
145 return (we_mca_lookup(ma
->ma_id
) != NULL
);
149 we_mca_attach(device_t parent
, device_t self
, void *aux
)
151 struct we_softc
*wsc
= device_private(self
);
152 struct dp8390_softc
*sc
= &wsc
->sc_dp8390
;
153 struct mca_attach_args
*ma
= aux
;
154 const struct we_mca_product
*wep
;
155 bus_space_tag_t nict
, asict
, memt
;
156 bus_space_handle_t nich
, asich
, memh
;
158 int irq
, iobase
, maddr
;
159 int pos2
, pos3
, pos5
;
163 pos2
= mca_conf_read(ma
->ma_mc
, ma
->ma_slot
, 2);
164 pos3
= mca_conf_read(ma
->ma_mc
, ma
->ma_slot
, 3);
165 pos5
= mca_conf_read(ma
->ma_mc
, ma
->ma_slot
, 5);
168 * POS registers differ a lot between 8003 and 8013, so they are
169 * divided to two sections.
171 * 8003: POS register 2: (adf pos0)
173 * 0 0 1 \_____/ \__ enable: 0=adapter disabled, 1=adapter enabled
174 * \____ Adapter I/O Space: 0x200-0x21F + XX*0x20
176 * 8003: POS register 3: (adf pos1)
179 * \______ Shared Ram Space (16K Bytes):
180 * 0xC0000-0xC3FFF + XX * 0x4000
182 * 8003: POS register 5: (adf pos3)
185 * \__ Interrupt Level: 00=3 01=4 10=10 11=15
187 * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
189 * 8013: POS register 2: (adf pos0)
191 * \____/ \__ enable: 0=adapter disabled, 1=adapter enabled
192 * \___________ Adapter I/O Space: 0x0800-0x081F + XX * 0x1000
194 * 8013: POS register 3: (adf pos1)
197 * | | \__ Shared RAM Base Address
198 * | | 0xc0000 + ((xx & 0x0f) * 0x2000)
199 * | \____________ Ram size: 0 = 8k, 1 = 16k
200 * | some size and address combinations are
201 * | not supported, varies by card :(
202 * \__________________ If set, add 0xf00000 to shared RAM base addr
203 * puts shared RAM near top of 16MB address space
205 * 8013: POS register 5: (adf pos3)
208 * \ \__ Media Select: 00=TwPr (no link) 10=BNC
209 * \ 01=AUI|AUI or 10BaseT
210 * \____ Interrupt Level: 00=3 01=4 10=10 11=14
213 wep
= we_mca_lookup(ma
->ma_id
);
216 aprint_error("\n%s: where did the card go?\n",
222 if (wep
->we_flag
& WD_8003
) {
224 iobase
= 0x200 + (((pos2
& 0x0e) >> 1) * 0x020);
225 maddr
= 0xC0000 + (((pos3
& 0x1c) >> 2) * 0x04000);
226 irq
= we_mca_irq
[(pos5
& 0x03)];
227 sc
->mem_size
= 16384;
230 iobase
= 0x800 + (((pos2
& 0xf0) >> 4) * 0x1000);
231 maddr
= 0xC0000 + ((pos3
& 0x0f) * 0x2000)
232 + ((pos3
& 0x80) ? 0xF00000 : 0);
233 irq
= we_mca_irq
[(pos5
& 0x0c) >> 2];
234 sc
->mem_size
= (pos3
& 0x10) ? 16384 : 8192;
237 nict
= asict
= ma
->ma_iot
;
240 aprint_normal(" slot %d port %#x-%#x mem %#x-%#x irq %d: %s\n",
242 iobase
, iobase
+ WE_NPORTS
- 1,
243 maddr
, maddr
+ sc
->mem_size
- 1,
246 /* Map the device. */
247 if (bus_space_map(asict
, iobase
, WE_NPORTS
, 0, &asich
)) {
248 aprint_error_dev(self
, "can't map nic i/o space\n");
252 if (bus_space_subregion(asict
, asich
, WE_NIC_OFFSET
, WE_NIC_NPORTS
,
254 aprint_error_dev(self
, "can't subregion i/o space\n");
258 wsc
->sc_type
= wep
->we_type
;
259 /* all cards we support are 16bit native (no need for reset) */
260 wsc
->sc_flags
= WE_16BIT_ENABLE
|WE_16BIT_NOTOGGLE
;
262 typestr
= wep
->we_typestr
;
267 if (bus_space_map(memt
, maddr
, sc
->mem_size
, 0, &memh
)) {
268 aprint_error_dev(self
, "can't map shared memory %#x-%#x\n",
269 maddr
, maddr
+ sc
->mem_size
- 1);
273 wsc
->sc_asict
= asict
;
274 wsc
->sc_asich
= asich
;
282 wsc
->sc_maddr
= maddr
;
284 /* Interface is always enabled. */
287 wsc
->sc_init_hook
= we_mca_init_hook
;
289 if (we_config(self
, wsc
, typestr
))
292 /* Map and establish the interrupt. */
293 wsc
->sc_ih
= mca_intr_establish(ma
->ma_mc
, irq
,
294 IPL_NET
, dp8390_intr
, sc
);
295 if (wsc
->sc_ih
== NULL
) {
296 aprint_error_dev(self
, "can't establish interrupt\n");
302 we_mca_init_hook(struct we_softc
*wsc
)
305 * This quirk really needs to be here, at least for WD8003W/A. Without
306 * this, the card doesn't send any interrupts in 16bit mode. The quirk
307 * was taken from Linux smc-mca.c driver.
308 * I do not know why it's necessary. I don't want to know. It works
309 * and that is enough for me.
311 bus_space_write_1(wsc
->sc_asict
, wsc
->sc_asich
, WE_LAAR
, 0x04);
312 wsc
->sc_laar_proto
|= 0x04;