if_ex_pci.c revision 1.2 1 /* $NetBSD: if_ex_pci.c,v 1.2 1998/11/07 16:53:19 drochner Exp $ */
2
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Frank van der Linden.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include "opt_inet.h"
40 #include "opt_ns.h"
41 #include "bpfilter.h"
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/mbuf.h>
46 #include <sys/socket.h>
47 #include <sys/ioctl.h>
48 #include <sys/errno.h>
49 #include <sys/syslog.h>
50 #include <sys/select.h>
51 #include <sys/device.h>
52
53 #include <net/if.h>
54 #include <net/if_dl.h>
55 #include <net/if_ether.h>
56 #include <net/if_media.h>
57
58 #ifdef INET
59 #include <netinet/in.h>
60 #include <netinet/in_systm.h>
61 #include <netinet/in_var.h>
62 #include <netinet/ip.h>
63 #include <netinet/if_inarp.h>
64 #endif
65
66 #ifdef NS
67 #include <netns/ns.h>
68 #include <netns/ns_if.h>
69 #endif
70
71 #if NBPFILTER > 0
72 #include <net/bpf.h>
73 #include <net/bpfdesc.h>
74 #endif
75
76 #include <machine/cpu.h>
77 #include <machine/bus.h>
78 #include <machine/intr.h>
79
80 #include <dev/mii/miivar.h>
81 #include <dev/mii/mii.h>
82
83 #include <dev/ic/elink3var.h>
84 #include <dev/ic/elink3reg.h>
85 #include <dev/ic/elinkxlreg.h>
86 #include <dev/ic/elinkxlvar.h>
87
88 #include <dev/pci/pcivar.h>
89 #include <dev/pci/pcireg.h>
90 #include <dev/pci/pcidevs.h>
91
92 /*
93 * PCI constants.
94 * XXX These should be in a common file!
95 */
96 #define PCI_CONN 0x48 /* Connector type */
97 #define PCI_CBIO 0x10 /* Configuration Base IO Address */
98 #define PCI_POWERCTL 0xe0
99
100 int ex_pci_match __P((struct device *, struct cfdata *, void *));
101 void ex_pci_attach __P((struct device *, struct device *, void *));
102
103 struct cfattach ex_pci_ca = {
104 sizeof(struct ex_softc), ex_pci_match, ex_pci_attach
105 };
106
107 int
108 ex_pci_match(parent, match, aux)
109 struct device *parent;
110 struct cfdata *match;
111 void *aux;
112 {
113 struct pci_attach_args *pa = (struct pci_attach_args *) aux;
114
115 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_3COM)
116 return 0;
117
118 switch (PCI_PRODUCT(pa->pa_id)) {
119 case PCI_PRODUCT_3COM_3C900TPO:
120 case PCI_PRODUCT_3COM_3C900COMBO:
121 case PCI_PRODUCT_3COM_3C905TX:
122 case PCI_PRODUCT_3COM_3C905T4:
123 case PCI_PRODUCT_3COM_3C900BTPO:
124 case PCI_PRODUCT_3COM_3C900BCOMBO:
125 case PCI_PRODUCT_3COM_3C905BT4:
126 case PCI_PRODUCT_3COM_3C905BTX:
127 break;
128 default:
129 return 0;
130 }
131
132 return 2; /* better than ep_pci */
133 }
134
135 void
136 ex_pci_attach(parent, self, aux)
137 struct device *parent, *self;
138 void *aux;
139 {
140 struct ex_softc *sc = (void *)self;
141 struct pci_attach_args *pa = aux;
142 pci_chipset_tag_t pc = pa->pa_pc;
143 pci_intr_handle_t ih;
144 char *model;
145 const char *intrstr = NULL;
146 int pmode;
147
148 if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
149 &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) {
150 printf(": can't map i/o space\n");
151 return;
152 }
153
154 sc->sc_dmat = pa->pa_dmat;
155
156 sc->ex_bustype = EX_BUS_PCI;
157 sc->ex_conf = 0;
158
159 switch (PCI_PRODUCT(pa->pa_id)) {
160 case PCI_PRODUCT_3COM_3C900TPO:
161 case PCI_PRODUCT_3COM_3C900COMBO:
162 model = "3Com 3C900 Ethernet";
163 break;
164 case PCI_PRODUCT_3COM_3C905TX:
165 case PCI_PRODUCT_3COM_3C905T4:
166 sc->ex_conf = EX_CONF_MII;
167 model = "3Com 3C905 Ethernet";
168 break;
169 case PCI_PRODUCT_3COM_3C900BTPO:
170 case PCI_PRODUCT_3COM_3C900BCOMBO:
171 sc->ex_conf = EX_CONF_90XB;
172 model = "3Com 3C900B Ethernet";
173 break;
174 case PCI_PRODUCT_3COM_3C905BTX:
175 case PCI_PRODUCT_3COM_3C905BT4:
176 sc->ex_conf = (EX_CONF_MII | EX_CONF_90XB);
177 if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3COM_3C905BTX)
178 sc->ex_conf |= EX_CONF_INTPHY;
179 model = "3Com 3C905B Ethernet";
180 break;
181 default:
182 model = "unknown model!";
183 break;
184 }
185
186 printf(": %s\n", model);
187
188 sc->enable = NULL;
189 sc->disable = NULL;
190 sc->enabled = 1;
191
192 /* Enable the card. */
193 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
194 pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) |
195 PCI_COMMAND_MASTER_ENABLE);
196
197 /* Get it out of power save mode if needed (BIOS bugs) */
198 if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, 0, 0)) {
199 pmode = pci_conf_read(pc, pa->pa_tag, PCI_POWERCTL) & 0x3;
200 if (pmode == 3) {
201 /*
202 * The card has lost all configuration data in
203 * this state, so punt.
204 */
205 printf("%s: unable to wake up from power state D3\n",
206 sc->sc_dev.dv_xname);
207 return;
208 }
209 if (pmode != 0) {
210 printf("%s: waking up from power state D%d\n",
211 sc->sc_dev.dv_xname, pmode);
212 pci_conf_write(pc, pa->pa_tag, PCI_POWERCTL, 0);
213 }
214 }
215
216 /* Map and establish the interrupt. */
217 if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin,
218 pa->pa_intrline, &ih)) {
219 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
220 return;
221 }
222 intrstr = pci_intr_string(pc, ih);
223 sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, ex_intr, sc);
224 if (sc->sc_ih == NULL) {
225 printf("%s: couldn't establish interrupt",
226 sc->sc_dev.dv_xname);
227 if (intrstr != NULL)
228 printf(" at %s", intrstr);
229 printf("\n");
230 return;
231 }
232 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
233
234 ex_config(sc);
235
236 }
237