1 /* $NetBSD: if_tra_mca.c,v 1.13 2009/05/12 13:15:24 cegger Exp $ */
4 * Copyright (c) 2004 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Driver for Tiara LANCard/E II and friends adapted from if_ate_mca.c
34 * by Dave J. Barnes 2004.
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: if_tra_mca.c,v 1.13 2009/05/12 13:15:24 cegger Exp $");
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/device.h>
43 #include <sys/socket.h>
44 #include <sys/syslog.h>
47 #include <net/if_ether.h>
48 #include <net/if_media.h>
53 #include <dev/ic/mb86950reg.h>
54 #include <dev/ic/mb86950var.h>
56 #include <dev/mca/mcavar.h>
57 #include <dev/mca/mcadevs.h>
59 int tiara_mca_match(device_t
, cfdata_t
, void *);
60 void tiara_mca_attach(device_t
, device_t
, void *);
62 #define TIARA_NPORTS 0x20 /* 32 */
63 #define TIARA_PROM_ID 24 /* offset to mac addr stored in prom */
66 struct mb86950_softc sc_mb86950
; /* real "mb86950" softc */
68 /* MCA-specific goo. */
69 void *sc_ih
; /* interrupt cookie */
72 CFATTACH_DECL(tra_mca
, sizeof(struct tiara_softc
),
73 tiara_mca_match
, tiara_mca_attach
, NULL
, NULL
);
75 static const struct tiara_mca_product
{
76 u_int32_t tra_prodid
; /* MCA product ID */
77 const char *tra_name
; /* device name */
78 } tiara_mca_products
[] = {
79 { MCA_PRODUCT_TIARA
, "Tiara LANCard/E2"},
80 { MCA_PRODUCT_TIARA_TP
, "Tiara LANCard/E2 TP"},
81 { MCA_PRODUCT_SMC3016
, "SMC 3016/MC"},
85 static const struct tiara_mca_product
*tiara_mca_lookup(u_int32_t
);
87 static const struct tiara_mca_product
*
88 tiara_mca_lookup(u_int32_t id
)
90 const struct tiara_mca_product
*tra_p
;
92 for (tra_p
= tiara_mca_products
; tra_p
->tra_name
!= NULL
; tra_p
++)
93 if (id
== tra_p
->tra_prodid
)
100 tiara_mca_match(device_t parent
, cfdata_t match
,
103 struct mca_attach_args
*ma
= (struct mca_attach_args
*) aux
;
105 if (tiara_mca_lookup(ma
->ma_id
) != NULL
)
111 /* see POS diagrams below for explanation */
112 static const int tiara_irq
[] = {
115 static const int smc_iobase
[] = {
116 0x300, 0x340, 0x360, 0x1980, 0x2000, 0x5680, 0x5900, 0x8080
118 static const int smc_irq
[] = {
119 9, 10, 11, 15, 3, 5, 7, 4
123 tiara_mca_attach(device_t parent
, device_t self
, void *aux
)
125 struct tiara_softc
*isc
= device_private(self
);
126 struct mb86950_softc
*sc
= &isc
->sc_mb86950
;
127 struct mca_attach_args
*ma
= aux
;
128 bus_space_tag_t iot
= ma
->ma_iot
;
129 bus_space_handle_t ioh
;
130 u_int8_t myea
[ETHER_ADDR_LEN
];
132 int iobase
= 0, irq
= 0;
133 const struct tiara_mca_product
*tra_p
;
135 pos2
= mca_conf_read(ma
->ma_mc
, ma
->ma_slot
, 2);
137 tra_p
= tiara_mca_lookup(ma
->ma_id
);
139 switch (tra_p
->tra_prodid
) {
141 case MCA_PRODUCT_TIARA
:
142 case MCA_PRODUCT_TIARA_TP
:
144 * POS register 2: (adf pos0)
146 * \_____/ \_/ \ \__ enable: 0=disabled, 1=enabled
147 * \ \ \___ boot rom: 0=disabled, 1=enabled
148 * \ \______ IRQ 00=3 01=4 10=7 11=9
149 * \_________ Base I/O Port
150 * 0000=0x1200 0001=0x1220 ... 1110=0x13c0 1111=0x13e0
152 * POS register 3: (adf pos1) not used
153 * POS register 4: (adf pos2) not used
155 * POS register 5: (adf pos3) ignored
161 iobase
= 0x1200 + ((pos2
& 0xf0) << 1);
162 irq
= tiara_irq
[((pos2
& 0x0c) >> 2)];
164 /* XXX SWAG for number pkts. */
165 /* My Tiara LANCard has 128K memory ?!? */
167 sc
->rxb_num_pkt
= (65535 - 8192 - 4) / 64;
172 case MCA_PRODUCT_SMC3016
:
174 * POS register 2: (adf pos0)
176 * \_____/ \___/ \__ enable: 0=disabled, 1=enabled
177 * \ \_____ I/O Address (see ioaddr table)
178 * \__________ IRQ (see irq table)
180 * POS register 3: (adf pos1) ignored
183 * \____EPROM Address (0000 = not used)
185 iobase
= smc_iobase
[((pos2
& 0x0e) >> 1)];
186 if ((pos2
& 0x80) != 0)
187 irq
= smc_irq
[((pos2
& 0x70) >> 4)];
189 aprint_error_dev(&sc
->sc_dev
, "unsupported irq selected\n");
193 /* XXX SWAG for number pkts. */
194 /* The SMC3016 has a 12K rx buffer and a 4k tx buffer */
196 sc
->rxb_num_pkt
= (12288 - 4) / 64;
204 tra_p
= tiara_mca_lookup(ma
->ma_id
);
207 aprint_error_dev(&sc
->sc_dev
, "where did the card go?\n");
212 printf(" slot %d ports %#x-%#x irq %d: %s\n", ma
->ma_slot
+ 1,iobase
, iobase
+ TIARA_NPORTS
, irq
, tra_p
->tra_name
);
215 if (bus_space_map(iot
, iobase
, TIARA_NPORTS
, 0, &ioh
)) {
216 aprint_error_dev(&sc
->sc_dev
, "can't map i/o space\n");
223 /* Get ethernet address from PROM */
224 bus_space_read_region_1(iot
, ioh
, TIARA_PROM_ID
, myea
, ETHER_ADDR_LEN
);
226 /* This interface is always enabled. */
228 sc->sc_stat |= NIC_STAT_ENABLED;
232 * Do generic MB86950 attach.
234 mb86950_attach(sc
, myea
);
237 mb86950_config(sc
, NULL
, 0, 0);
239 /* Establish the interrupt handler. */
240 isc
->sc_ih
= mca_intr_establish(ma
->ma_mc
, irq
, IPL_NET
,
242 if (isc
->sc_ih
== NULL
) {
243 aprint_error_dev(&sc
->sc_dev
, "couldn't establish interrupt handler\n");