Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / if_le_pci.c
blob37ac046d5431fd81bbdc8093a26a27e2d1b79bdd
1 /* $NetBSD: if_le_pci.c,v 1.48 2008/04/04 12:25:07 tsutsui Exp $ */
3 /*-
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
9 * Simulation Facility, NASA Ames Research Center.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
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.
33 /*-
34 * Copyright (c) 1992, 1993
35 * The Regents of the University of California. All rights reserved.
37 * This code is derived from software contributed to Berkeley by
38 * Ralph Campbell and Rick Macklem.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
64 * @(#)if_le.c 8.2 (Berkeley) 11/16/93
67 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: if_le_pci.c,v 1.48 2008/04/04 12:25:07 tsutsui Exp $");
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/mbuf.h>
73 #include <sys/syslog.h>
74 #include <sys/socket.h>
75 #include <sys/device.h>
77 #include <uvm/uvm_extern.h>
79 #include <net/if.h>
80 #include <net/if_ether.h>
81 #include <net/if_media.h>
83 #include <sys/cpu.h>
84 #include <sys/bus.h>
85 #include <sys/intr.h>
87 #include <dev/pci/pcireg.h>
88 #include <dev/pci/pcivar.h>
89 #include <dev/pci/pcidevs.h>
91 #include <dev/ic/lancereg.h>
92 #include <dev/ic/lancevar.h>
93 #include <dev/ic/am79900reg.h>
94 #include <dev/ic/am79900var.h>
96 #include <dev/pci/if_levar.h>
98 static int le_pci_match(device_t, cfdata_t, void *);
99 static void le_pci_attach(device_t, device_t, void *);
100 static int le_pci_mediachange(struct lance_softc *);
102 CFATTACH_DECL_NEW(le_pci, sizeof(struct le_softc),
103 le_pci_match, le_pci_attach, NULL, NULL);
106 * PCI constants.
107 * XXX These should be in a common file!
109 #define PCI_CBIO 0x10 /* Configuration Base IO Address */
111 #define LE_PCI_MEMSIZE 16384
113 static int le_pci_supmedia[] = {
114 IFM_ETHER|IFM_AUTO,
115 IFM_ETHER|IFM_AUTO|IFM_FDX,
116 IFM_ETHER|IFM_10_T,
117 IFM_ETHER|IFM_10_T|IFM_FDX,
118 IFM_ETHER|IFM_10_5,
119 IFM_ETHER|IFM_10_5|IFM_FDX,
122 static void
123 le_pci_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val)
125 struct le_softc *lesc = (struct le_softc *)sc;
126 bus_space_tag_t iot = lesc->sc_iot;
127 bus_space_handle_t ioh = lesc->sc_ioh;
129 bus_space_write_2(iot, ioh, lesc->sc_rap, port);
130 bus_space_write_2(iot, ioh, lesc->sc_rdp, val);
133 static uint16_t
134 le_pci_rdcsr(struct lance_softc *sc, uint16_t port)
136 struct le_softc *lesc = (struct le_softc *)sc;
137 bus_space_tag_t iot = lesc->sc_iot;
138 bus_space_handle_t ioh = lesc->sc_ioh;
139 uint16_t val;
141 bus_space_write_2(iot, ioh, lesc->sc_rap, port);
142 val = bus_space_read_2(iot, ioh, lesc->sc_rdp);
143 return (val);
146 static int
147 le_pci_mediachange(struct lance_softc *sc)
149 struct le_softc *lesc = (struct le_softc *)sc;
150 bus_space_tag_t iot = lesc->sc_iot;
151 bus_space_handle_t ioh = lesc->sc_ioh;
152 int newmedia = sc->sc_media.ifm_media;
153 uint16_t reg;
155 if (IFM_SUBTYPE(newmedia) !=
156 IFM_SUBTYPE(lesc->sc_currentmedia)) {
157 if (IFM_SUBTYPE(newmedia) == IFM_AUTO) {
158 /* switch to autoselect - BCR2 bit 1 */
159 bus_space_write_2(iot, ioh, PCNET_PCI_RAP, 2);
160 reg = bus_space_read_2(iot, ioh, PCNET_PCI_BDP);
161 reg |= 2;
162 bus_space_write_2(iot, ioh, PCNET_PCI_RAP, 2);
163 bus_space_write_2(iot, ioh, PCNET_PCI_BDP, reg);
164 } else {
165 /* force media type (in init block) */
166 lance_reset(sc);
167 if (IFM_SUBTYPE(newmedia) == IFM_10_T)
168 sc->sc_initmodemedia = 1; /* UTP */
169 else
170 sc->sc_initmodemedia = 0; /* AUI */
171 lance_init(&sc->sc_ethercom.ec_if);
173 if (IFM_SUBTYPE(lesc->sc_currentmedia) == IFM_AUTO) {
174 /* take away autoselect - BCR2 bit 1 */
175 bus_space_write_2(iot, ioh, PCNET_PCI_RAP, 2);
176 reg = bus_space_read_2(iot, ioh, PCNET_PCI_BDP);
177 reg &= ~2;
178 bus_space_write_2(iot, ioh, PCNET_PCI_RAP, 2);
179 bus_space_write_2(iot, ioh, PCNET_PCI_BDP, reg);
185 if ((IFM_OPTIONS(newmedia) ^ IFM_OPTIONS(lesc->sc_currentmedia))
186 & IFM_FDX) {
187 /* toggle full duplex - BCR9 */
188 bus_space_write_2(iot, ioh, PCNET_PCI_RAP, 9);
189 reg = bus_space_read_2(iot, ioh, PCNET_PCI_BDP);
190 if (IFM_OPTIONS(newmedia) & IFM_FDX) {
191 reg |= 1; /* FDEN */
192 /* allow FDX on AUI only if explicitly chosen,
193 not in autoselect mode */
194 if (IFM_SUBTYPE(newmedia) == IFM_10_5)
195 reg |= 2; /* AUIFD */
196 else
197 reg &= ~2;
198 } else
199 reg &= ~1;
200 bus_space_write_2(iot, ioh, PCNET_PCI_RAP, 9);
201 bus_space_write_2(iot, ioh, PCNET_PCI_BDP, reg);
204 lesc->sc_currentmedia = newmedia;
205 return (0);
208 static int
209 le_pci_match(device_t parent, cfdata_t cf, void *aux)
211 struct pci_attach_args *pa = aux;
213 if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_AMD)
214 return (0);
216 switch (PCI_PRODUCT(pa->pa_id)) {
217 case PCI_PRODUCT_AMD_PCNET_PCI:
218 return (1);
221 return (0);
224 static void
225 le_pci_attach(device_t parent, device_t self, void *aux)
227 struct le_softc *lesc = device_private(self);
228 struct lance_softc *sc = &lesc->sc_am79900.lsc;
229 struct pci_attach_args *pa = aux;
230 pci_intr_handle_t ih;
231 bus_space_tag_t iot;
232 bus_space_handle_t ioh;
233 bus_dma_tag_t dmat = pa->pa_dmat;
234 bus_dma_segment_t seg;
235 pci_chipset_tag_t pc = pa->pa_pc;
236 pcireg_t csr;
237 int i, rseg;
238 const char *model, *intrstr;
240 sc->sc_dev = self;
242 switch (PCI_PRODUCT(pa->pa_id)) {
243 case PCI_PRODUCT_AMD_PCNET_PCI:
244 model = "PCnet-PCI Ethernet";
245 lesc->sc_rap = PCNET_PCI_RAP;
246 lesc->sc_rdp = PCNET_PCI_RDP;
247 break;
249 default:
250 model = "unknown model!";
253 aprint_normal(": %s\n", model);
255 if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0,
256 &iot, &ioh, NULL, NULL)) {
257 aprint_error_dev(self, "can't map I/O space\n");
258 return;
262 * Extract the physical MAC address from the ROM.
264 for (i = 0; i < sizeof(sc->sc_enaddr); i++)
265 sc->sc_enaddr[i] = bus_space_read_1(iot, ioh, i);
267 lesc->sc_iot = iot;
268 lesc->sc_ioh = ioh;
269 lesc->sc_dmat = dmat;
272 * Allocate a DMA area for the card.
274 if (bus_dmamem_alloc(dmat, LE_PCI_MEMSIZE, PAGE_SIZE, 0, &seg, 1,
275 &rseg, BUS_DMA_NOWAIT)) {
276 aprint_error_dev(self, "couldn't allocate memory for card\n");
277 return;
279 if (bus_dmamem_map(dmat, &seg, rseg, LE_PCI_MEMSIZE,
280 (void **)&sc->sc_mem,
281 BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
282 aprint_error_dev(self, "couldn't map memory for card\n");
283 return;
287 * Create and load the DMA map for the DMA area.
289 if (bus_dmamap_create(dmat, LE_PCI_MEMSIZE, 1,
290 LE_PCI_MEMSIZE, 0, BUS_DMA_NOWAIT, &lesc->sc_dmam)) {
291 aprint_error_dev(self, "couldn't create DMA map\n");
292 bus_dmamem_free(dmat, &seg, rseg);
293 return;
295 if (bus_dmamap_load(dmat, lesc->sc_dmam,
296 sc->sc_mem, LE_PCI_MEMSIZE, NULL, BUS_DMA_NOWAIT)) {
297 aprint_error_dev(self, "coundn't load DMA map\n");
298 bus_dmamem_free(dmat, &seg, rseg);
299 return;
302 sc->sc_conf3 = 0;
303 sc->sc_addr = lesc->sc_dmam->dm_segs[0].ds_addr;
304 sc->sc_memsize = LE_PCI_MEMSIZE;
306 sc->sc_copytodesc = lance_copytobuf_contig;
307 sc->sc_copyfromdesc = lance_copyfrombuf_contig;
308 sc->sc_copytobuf = lance_copytobuf_contig;
309 sc->sc_copyfrombuf = lance_copyfrombuf_contig;
310 sc->sc_zerobuf = lance_zerobuf_contig;
312 sc->sc_rdcsr = le_pci_rdcsr;
313 sc->sc_wrcsr = le_pci_wrcsr;
314 sc->sc_hwinit = NULL;
316 sc->sc_supmedia = le_pci_supmedia;
317 sc->sc_nsupmedia = sizeof(le_pci_supmedia) / sizeof(int);
318 sc->sc_defaultmedia = le_pci_supmedia[0];
319 sc->sc_mediachange = le_pci_mediachange;
320 lesc->sc_currentmedia = le_pci_supmedia[0];
322 aprint_normal("%s", device_xname(self));
323 am79900_config(&lesc->sc_am79900);
325 /* Chip is stopped. Set "software style" to 32-bit. */
326 bus_space_write_2(iot, ioh, PCNET_PCI_RAP, 20);
327 bus_space_write_2(iot, ioh, PCNET_PCI_BDP, 2);
329 /* Enable the card. */
330 csr = pci_conf_read(pc, pa->pa_tag,
331 PCI_COMMAND_STATUS_REG);
332 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
333 csr | PCI_COMMAND_MASTER_ENABLE);
335 /* Map and establish the interrupt. */
336 if (pci_intr_map(pa, &ih)) {
337 aprint_error_dev(self, "couldn't map interrupt\n");
338 return;
340 intrstr = pci_intr_string(pc, ih);
341 lesc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, am79900_intr, sc);
342 if (lesc->sc_ih == NULL) {
343 aprint_error_dev(self, "couldn't establish interrupt");
344 if (intrstr != NULL)
345 aprint_error(" at %s", intrstr);
346 aprint_error("\n");
347 return;
349 aprint_normal_dev(self, "interrupting at %s\n", intrstr);