Deleted Added
full compact
if_le_pci.c (158647) if_le_pci.c (158663)
1/* $NetBSD: if_le_pci.c,v 1.43 2005/12/11 12:22:49 christos Exp $ */
2
3/*-
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
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.
10 *
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.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40/*-
41 * Copyright (c) 1992, 1993
42 * The Regents of the University of California. All rights reserved.
43 *
44 * This code is derived from software contributed to Berkeley by
45 * Ralph Campbell and Rick Macklem.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 * @(#)if_le.c 8.2 (Berkeley) 11/16/93
72 */
73
74#include <sys/cdefs.h>
1/* $NetBSD: if_le_pci.c,v 1.43 2005/12/11 12:22:49 christos Exp $ */
2
3/*-
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
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.
10 *
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.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40/*-
41 * Copyright (c) 1992, 1993
42 * The Regents of the University of California. All rights reserved.
43 *
44 * This code is derived from software contributed to Berkeley by
45 * Ralph Campbell and Rick Macklem.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice, this list of conditions and the following disclaimer.
52 * 2. Redistributions in binary form must reproduce the above copyright
53 * notice, this list of conditions and the following disclaimer in the
54 * documentation and/or other materials provided with the distribution.
55 * 3. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 * @(#)if_le.c 8.2 (Berkeley) 11/16/93
72 */
73
74#include <sys/cdefs.h>
75__FBSDID("$FreeBSD: head/sys/dev/le/if_le_pci.c 158647 2006-05-16 12:15:39Z ru $");
75__FBSDID("$FreeBSD: head/sys/dev/le/if_le_pci.c 158663 2006-05-16 21:04:01Z marius $");
76
77#include <sys/param.h>
78#include <sys/systm.h>
79#include <sys/bus.h>
80#include <sys/endian.h>
81#include <sys/kernel.h>
82#include <sys/lock.h>
83#include <sys/module.h>
84#include <sys/mutex.h>
85#include <sys/resource.h>
86#include <sys/rman.h>
87#include <sys/socket.h>
88
89#include <net/ethernet.h>
90#include <net/if.h>
91#include <net/if_media.h>
92
93#include <machine/bus.h>
94#include <machine/resource.h>
95
96#include <dev/pci/pcireg.h>
97#include <dev/pci/pcivar.h>
98
99#include <dev/le/lancereg.h>
100#include <dev/le/lancevar.h>
101#include <dev/le/am79900var.h>
102
103#define AMD_VENDOR 0x1022
104#define AMD_PCNET_PCI 0x2000
105#define AMD_PCNET_HOME 0x2001
76
77#include <sys/param.h>
78#include <sys/systm.h>
79#include <sys/bus.h>
80#include <sys/endian.h>
81#include <sys/kernel.h>
82#include <sys/lock.h>
83#include <sys/module.h>
84#include <sys/mutex.h>
85#include <sys/resource.h>
86#include <sys/rman.h>
87#include <sys/socket.h>
88
89#include <net/ethernet.h>
90#include <net/if.h>
91#include <net/if_media.h>
92
93#include <machine/bus.h>
94#include <machine/resource.h>
95
96#include <dev/pci/pcireg.h>
97#include <dev/pci/pcivar.h>
98
99#include <dev/le/lancereg.h>
100#include <dev/le/lancevar.h>
101#include <dev/le/am79900var.h>
102
103#define AMD_VENDOR 0x1022
104#define AMD_PCNET_PCI 0x2000
105#define AMD_PCNET_HOME 0x2001
106#define PCNET_MEMSIZE 16384
106#define PCNET_MEMSIZE (32*1024)
107#define PCNET_PCI_RDP 0x10
108#define PCNET_PCI_RAP 0x12
109#define PCNET_PCI_BDP 0x16
110
111struct le_pci_softc {
112 struct am79900_softc sc_am79900; /* glue to MI code */
113
114 int sc_rrid;
115 struct resource *sc_rres;
116 bus_space_tag_t sc_regt;
117 bus_space_handle_t sc_regh;
118
119 int sc_irid;
120 struct resource *sc_ires;
121 void *sc_ih;
122
123 bus_dma_tag_t sc_pdmat;
124 bus_dma_tag_t sc_dmat;
125 bus_dmamap_t sc_dmam;
126};
127
128static device_probe_t le_pci_probe;
129static device_attach_t le_pci_attach;
130static device_detach_t le_pci_detach;
131static device_resume_t le_pci_resume;
132static device_suspend_t le_pci_suspend;
133
134static device_method_t le_pci_methods[] = {
135 /* Device interface */
136 DEVMETHOD(device_probe, le_pci_probe),
137 DEVMETHOD(device_attach, le_pci_attach),
138 DEVMETHOD(device_detach, le_pci_detach),
139 /* We can just use the suspend method here. */
140 DEVMETHOD(device_shutdown, le_pci_suspend),
141 DEVMETHOD(device_suspend, le_pci_suspend),
142 DEVMETHOD(device_resume, le_pci_resume),
143
144 { 0, 0 }
145};
146
147DEFINE_CLASS_0(le, le_pci_driver, le_pci_methods, sizeof(struct le_pci_softc));
148DRIVER_MODULE(le, pci, le_pci_driver, le_devclass, 0, 0);
107#define PCNET_PCI_RDP 0x10
108#define PCNET_PCI_RAP 0x12
109#define PCNET_PCI_BDP 0x16
110
111struct le_pci_softc {
112 struct am79900_softc sc_am79900; /* glue to MI code */
113
114 int sc_rrid;
115 struct resource *sc_rres;
116 bus_space_tag_t sc_regt;
117 bus_space_handle_t sc_regh;
118
119 int sc_irid;
120 struct resource *sc_ires;
121 void *sc_ih;
122
123 bus_dma_tag_t sc_pdmat;
124 bus_dma_tag_t sc_dmat;
125 bus_dmamap_t sc_dmam;
126};
127
128static device_probe_t le_pci_probe;
129static device_attach_t le_pci_attach;
130static device_detach_t le_pci_detach;
131static device_resume_t le_pci_resume;
132static device_suspend_t le_pci_suspend;
133
134static device_method_t le_pci_methods[] = {
135 /* Device interface */
136 DEVMETHOD(device_probe, le_pci_probe),
137 DEVMETHOD(device_attach, le_pci_attach),
138 DEVMETHOD(device_detach, le_pci_detach),
139 /* We can just use the suspend method here. */
140 DEVMETHOD(device_shutdown, le_pci_suspend),
141 DEVMETHOD(device_suspend, le_pci_suspend),
142 DEVMETHOD(device_resume, le_pci_resume),
143
144 { 0, 0 }
145};
146
147DEFINE_CLASS_0(le, le_pci_driver, le_pci_methods, sizeof(struct le_pci_softc));
148DRIVER_MODULE(le, pci, le_pci_driver, le_devclass, 0, 0);
149MODULE_DEPEND(le_DRIVER_NAME, ether, 1, 1, 1);
149MODULE_DEPEND(le, ether, 1, 1, 1);
150
151static const int le_home_supmedia[] = {
152 IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, 0)
153};
154
155static const int le_pci_supmedia[] = {
156 IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0),
157 IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, IFM_FDX, 0),
158 IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0),
159 IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, 0),
160 IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0),
161 IFM_MAKEWORD(IFM_ETHER, IFM_10_5, IFM_FDX, 0)
162};
163
164static void le_pci_wrbcr(struct lance_softc *, uint16_t, uint16_t);
165static uint16_t le_pci_rdbcr(struct lance_softc *, uint16_t);
166static void le_pci_wrcsr(struct lance_softc *, uint16_t, uint16_t);
167static uint16_t le_pci_rdcsr(struct lance_softc *, uint16_t);
168static int le_pci_mediachange(struct lance_softc *);
169static void le_pci_hwreset(struct lance_softc *);
170static bus_dmamap_callback_t le_pci_dma_callback;
171
172static void
173le_pci_wrbcr(struct lance_softc *sc, uint16_t port, uint16_t val)
174{
175 struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
176
177 bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
178 bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
179 BUS_SPACE_BARRIER_WRITE);
180 bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_BDP, val);
181}
182
183static uint16_t
184le_pci_rdbcr(struct lance_softc *sc, uint16_t port)
185{
186 struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
187
188 bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
189 bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
190 BUS_SPACE_BARRIER_WRITE);
191 return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_BDP));
192}
193
194static void
195le_pci_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val)
196{
197 struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
198
199 bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
200 bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
201 BUS_SPACE_BARRIER_WRITE);
202 bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP, val);
203}
204
205static uint16_t
206le_pci_rdcsr(struct lance_softc *sc, uint16_t port)
207{
208 struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
209
210 bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
211 bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
212 BUS_SPACE_BARRIER_WRITE);
213 return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP));
214}
215
216static int
217le_pci_mediachange(struct lance_softc *sc)
218{
219 struct ifmedia *ifm = &sc->sc_media;
220 uint16_t reg;
221
222 if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
223 return (EINVAL);
224
225 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1)
226 le_pci_wrbcr(sc, LE_BCR49,
227 (le_pci_rdbcr(sc, LE_BCR49) & ~LE_B49_PHYSEL) | 0x1);
228 else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO)
229 le_pci_wrbcr(sc, LE_BCR2,
230 le_pci_rdbcr(sc, LE_BCR2) | LE_B2_ASEL);
231 else {
232 le_pci_wrbcr(sc, LE_BCR2,
233 le_pci_rdbcr(sc, LE_BCR2) & ~LE_B2_ASEL);
234
235 reg = le_pci_rdcsr(sc, LE_CSR15);
236 reg &= ~LE_C15_PORTSEL(LE_PORTSEL_MASK);
237 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T)
238 reg |= LE_C15_PORTSEL(LE_PORTSEL_10T);
239 else
240 reg |= LE_C15_PORTSEL(LE_PORTSEL_AUI);
241 le_pci_wrcsr(sc, LE_CSR15, reg);
242 }
243
244 reg = le_pci_rdbcr(sc, LE_BCR9);
245 if (IFM_OPTIONS(ifm->ifm_media) & IFM_FDX) {
246 reg |= LE_B9_FDEN;
247 /*
248 * Allow FDX on AUI only if explicitly chosen,
249 * not in autoselect mode.
250 */
251 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_5)
252 reg |= LE_B9_AUIFD;
253 else
254 reg &= ~LE_B9_AUIFD;
255 } else
256 reg &= ~LE_B9_FDEN;
257 le_pci_wrbcr(sc, LE_BCR9, reg);
258
259 return (0);
260}
261
262static void
263le_pci_hwreset(struct lance_softc *sc)
264{
265
150
151static const int le_home_supmedia[] = {
152 IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, 0)
153};
154
155static const int le_pci_supmedia[] = {
156 IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0),
157 IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, IFM_FDX, 0),
158 IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0),
159 IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, 0),
160 IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0),
161 IFM_MAKEWORD(IFM_ETHER, IFM_10_5, IFM_FDX, 0)
162};
163
164static void le_pci_wrbcr(struct lance_softc *, uint16_t, uint16_t);
165static uint16_t le_pci_rdbcr(struct lance_softc *, uint16_t);
166static void le_pci_wrcsr(struct lance_softc *, uint16_t, uint16_t);
167static uint16_t le_pci_rdcsr(struct lance_softc *, uint16_t);
168static int le_pci_mediachange(struct lance_softc *);
169static void le_pci_hwreset(struct lance_softc *);
170static bus_dmamap_callback_t le_pci_dma_callback;
171
172static void
173le_pci_wrbcr(struct lance_softc *sc, uint16_t port, uint16_t val)
174{
175 struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
176
177 bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
178 bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
179 BUS_SPACE_BARRIER_WRITE);
180 bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_BDP, val);
181}
182
183static uint16_t
184le_pci_rdbcr(struct lance_softc *sc, uint16_t port)
185{
186 struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
187
188 bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
189 bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
190 BUS_SPACE_BARRIER_WRITE);
191 return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_BDP));
192}
193
194static void
195le_pci_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val)
196{
197 struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
198
199 bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
200 bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
201 BUS_SPACE_BARRIER_WRITE);
202 bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP, val);
203}
204
205static uint16_t
206le_pci_rdcsr(struct lance_softc *sc, uint16_t port)
207{
208 struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
209
210 bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
211 bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
212 BUS_SPACE_BARRIER_WRITE);
213 return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP));
214}
215
216static int
217le_pci_mediachange(struct lance_softc *sc)
218{
219 struct ifmedia *ifm = &sc->sc_media;
220 uint16_t reg;
221
222 if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
223 return (EINVAL);
224
225 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1)
226 le_pci_wrbcr(sc, LE_BCR49,
227 (le_pci_rdbcr(sc, LE_BCR49) & ~LE_B49_PHYSEL) | 0x1);
228 else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO)
229 le_pci_wrbcr(sc, LE_BCR2,
230 le_pci_rdbcr(sc, LE_BCR2) | LE_B2_ASEL);
231 else {
232 le_pci_wrbcr(sc, LE_BCR2,
233 le_pci_rdbcr(sc, LE_BCR2) & ~LE_B2_ASEL);
234
235 reg = le_pci_rdcsr(sc, LE_CSR15);
236 reg &= ~LE_C15_PORTSEL(LE_PORTSEL_MASK);
237 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T)
238 reg |= LE_C15_PORTSEL(LE_PORTSEL_10T);
239 else
240 reg |= LE_C15_PORTSEL(LE_PORTSEL_AUI);
241 le_pci_wrcsr(sc, LE_CSR15, reg);
242 }
243
244 reg = le_pci_rdbcr(sc, LE_BCR9);
245 if (IFM_OPTIONS(ifm->ifm_media) & IFM_FDX) {
246 reg |= LE_B9_FDEN;
247 /*
248 * Allow FDX on AUI only if explicitly chosen,
249 * not in autoselect mode.
250 */
251 if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_5)
252 reg |= LE_B9_AUIFD;
253 else
254 reg &= ~LE_B9_AUIFD;
255 } else
256 reg &= ~LE_B9_FDEN;
257 le_pci_wrbcr(sc, LE_BCR9, reg);
258
259 return (0);
260}
261
262static void
263le_pci_hwreset(struct lance_softc *sc)
264{
265
266 /* Chip is stopped. Set "software style" to 32-bit. */
267 le_pci_wrbcr(sc, LE_BCR20, LE_B20_SSTYLE_PCNETPCI2);
266 /* Chip is stopped. Set software style to ILACC (32-bit). */
267 le_pci_wrbcr(sc, LE_BCR20, LE_B20_SSTYLE_ILACC);
268}
269
270static void
271le_pci_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
272{
273 struct lance_softc *sc = (struct lance_softc *)xsc;
274
275 if (error != 0)
276 return;
277 KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__));
278 sc->sc_addr = segs[0].ds_addr;
279}
280
281static int
282le_pci_probe(device_t dev)
283{
284
285 if (pci_get_vendor(dev) != AMD_VENDOR)
286 return (ENXIO);
287
288 switch (pci_get_device(dev)) {
289 case AMD_PCNET_PCI:
268}
269
270static void
271le_pci_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
272{
273 struct lance_softc *sc = (struct lance_softc *)xsc;
274
275 if (error != 0)
276 return;
277 KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__));
278 sc->sc_addr = segs[0].ds_addr;
279}
280
281static int
282le_pci_probe(device_t dev)
283{
284
285 if (pci_get_vendor(dev) != AMD_VENDOR)
286 return (ENXIO);
287
288 switch (pci_get_device(dev)) {
289 case AMD_PCNET_PCI:
290 device_set_desc(dev, "AMD PCnet-PCI");
291 /* Let pcn(4) win. */
292 return (BUS_PROBE_LOW_PRIORITY);
290 case AMD_PCNET_HOME:
293 case AMD_PCNET_HOME:
291 device_set_desc(dev, "AMD PCnet Ethernet");
292 return (BUS_PROBE_DEFAULT);
294 device_set_desc(dev, "AMD PCnet-Home");
295 /* Let pcn(4) win. */
296 return (BUS_PROBE_LOW_PRIORITY);
293 default:
294 return (ENXIO);
295 }
296}
297
298static int
299le_pci_attach(device_t dev)
300{
301 struct le_pci_softc *lesc;
302 struct lance_softc *sc;
303 int error, i;
304
305 lesc = device_get_softc(dev);
306 sc = &lesc->sc_am79900.lsc;
307
308 LE_LOCK_INIT(sc, device_get_nameunit(dev));
309
310 pci_enable_busmaster(dev);
311 pci_enable_io(dev, PCIM_CMD_PORTEN);
312
313 lesc->sc_rrid = PCIR_BAR(0);
314 lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
315 &lesc->sc_rrid, RF_ACTIVE);
316 if (lesc->sc_rres == NULL) {
317 device_printf(dev, "cannot allocate registers\n");
318 error = ENXIO;
319 goto fail_mtx;
320 }
321 lesc->sc_regt = rman_get_bustag(lesc->sc_rres);
322 lesc->sc_regh = rman_get_bushandle(lesc->sc_rres);
323
324 lesc->sc_irid = 0;
325 if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
326 &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
327 device_printf(dev, "cannot allocate interrupt\n");
328 error = ENXIO;
329 goto fail_rres;
330 }
331
332 error = bus_dma_tag_create(
333 NULL, /* parent */
297 default:
298 return (ENXIO);
299 }
300}
301
302static int
303le_pci_attach(device_t dev)
304{
305 struct le_pci_softc *lesc;
306 struct lance_softc *sc;
307 int error, i;
308
309 lesc = device_get_softc(dev);
310 sc = &lesc->sc_am79900.lsc;
311
312 LE_LOCK_INIT(sc, device_get_nameunit(dev));
313
314 pci_enable_busmaster(dev);
315 pci_enable_io(dev, PCIM_CMD_PORTEN);
316
317 lesc->sc_rrid = PCIR_BAR(0);
318 lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
319 &lesc->sc_rrid, RF_ACTIVE);
320 if (lesc->sc_rres == NULL) {
321 device_printf(dev, "cannot allocate registers\n");
322 error = ENXIO;
323 goto fail_mtx;
324 }
325 lesc->sc_regt = rman_get_bustag(lesc->sc_rres);
326 lesc->sc_regh = rman_get_bushandle(lesc->sc_rres);
327
328 lesc->sc_irid = 0;
329 if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
330 &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
331 device_printf(dev, "cannot allocate interrupt\n");
332 error = ENXIO;
333 goto fail_rres;
334 }
335
336 error = bus_dma_tag_create(
337 NULL, /* parent */
334 PAGE_SIZE, 0, /* alignment, boundary */
338 1, 0, /* alignment, boundary */
335 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
336 BUS_SPACE_MAXADDR, /* highaddr */
337 NULL, NULL, /* filter, filterarg */
338 BUS_SPACE_MAXSIZE_32BIT, /* maxsize */
339 0, /* nsegments */
340 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
341 BUS_DMA_WAITOK, /* flags */
342 NULL, NULL, /* lockfunc, lockarg */
343 &lesc->sc_pdmat);
344 if (error != 0) {
345 device_printf(dev, "cannot allocate parent DMA tag\n");
346 goto fail_ires;
347 }
348
349 sc->sc_memsize = PCNET_MEMSIZE;
339 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
340 BUS_SPACE_MAXADDR, /* highaddr */
341 NULL, NULL, /* filter, filterarg */
342 BUS_SPACE_MAXSIZE_32BIT, /* maxsize */
343 0, /* nsegments */
344 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
345 BUS_DMA_WAITOK, /* flags */
346 NULL, NULL, /* lockfunc, lockarg */
347 &lesc->sc_pdmat);
348 if (error != 0) {
349 device_printf(dev, "cannot allocate parent DMA tag\n");
350 goto fail_ires;
351 }
352
353 sc->sc_memsize = PCNET_MEMSIZE;
354 /*
355 * For Am79C970A, Am79C971 and Am79C978 the init block must be 2-byte
356 * aligned and the ring descriptors must be 16-byte aligned when using
357 * a 32-bit software style.
358 */
350 error = bus_dma_tag_create(
351 lesc->sc_pdmat, /* parent */
359 error = bus_dma_tag_create(
360 lesc->sc_pdmat, /* parent */
352 1, 0, /* alignment, boundary */
361 16, 0, /* alignment, boundary */
353 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
354 BUS_SPACE_MAXADDR, /* highaddr */
355 NULL, NULL, /* filter, filterarg */
356 sc->sc_memsize, /* maxsize */
357 1, /* nsegments */
358 sc->sc_memsize, /* maxsegsize */
359 BUS_DMA_WAITOK, /* flags */
360 NULL, NULL, /* lockfunc, lockarg */
361 &lesc->sc_dmat);
362 if (error != 0) {
363 device_printf(dev, "cannot allocate buffer DMA tag\n");
364 goto fail_pdtag;
365 }
366
367 error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem,
368 BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam);
369 if (error != 0) {
370 device_printf(dev, "cannot allocate DMA buffer memory\n");
371 goto fail_dtag;
372 }
373
374 sc->sc_addr = 0;
375 error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem,
376 sc->sc_memsize, le_pci_dma_callback, sc, 0);
377 if (error != 0 || sc->sc_addr == 0) {
378 device_printf(dev, "cannot load DMA buffer map\n");
379 goto fail_dmem;
380 }
381
382 sc->sc_flags = LE_BSWAP;
383 sc->sc_conf3 = 0;
384
362 BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
363 BUS_SPACE_MAXADDR, /* highaddr */
364 NULL, NULL, /* filter, filterarg */
365 sc->sc_memsize, /* maxsize */
366 1, /* nsegments */
367 sc->sc_memsize, /* maxsegsize */
368 BUS_DMA_WAITOK, /* flags */
369 NULL, NULL, /* lockfunc, lockarg */
370 &lesc->sc_dmat);
371 if (error != 0) {
372 device_printf(dev, "cannot allocate buffer DMA tag\n");
373 goto fail_pdtag;
374 }
375
376 error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem,
377 BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam);
378 if (error != 0) {
379 device_printf(dev, "cannot allocate DMA buffer memory\n");
380 goto fail_dtag;
381 }
382
383 sc->sc_addr = 0;
384 error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem,
385 sc->sc_memsize, le_pci_dma_callback, sc, 0);
386 if (error != 0 || sc->sc_addr == 0) {
387 device_printf(dev, "cannot load DMA buffer map\n");
388 goto fail_dmem;
389 }
390
391 sc->sc_flags = LE_BSWAP;
392 sc->sc_conf3 = 0;
393
394 sc->sc_mediastatus = NULL;
385 switch (pci_get_device(dev)) {
386 case AMD_PCNET_HOME:
387 sc->sc_mediachange = le_pci_mediachange;
388 sc->sc_supmedia = le_home_supmedia;
389 sc->sc_nsupmedia = sizeof(le_home_supmedia) / sizeof(int);
390 sc->sc_defaultmedia = le_home_supmedia[0];
391 break;
392 default:
393 sc->sc_mediachange = le_pci_mediachange;
394 sc->sc_supmedia = le_pci_supmedia;
395 sc->sc_nsupmedia = sizeof(le_pci_supmedia) / sizeof(int);
396 sc->sc_defaultmedia = le_pci_supmedia[0];
397 }
398
399 /*
400 * Extract the physical MAC address from the ROM.
401 */
402 for (i = 0; i < sizeof(sc->sc_enaddr); i++)
403 sc->sc_enaddr[i] =
404 bus_space_read_1(lesc->sc_regt, lesc->sc_regh, i);
405
406 sc->sc_copytodesc = lance_copytobuf_contig;
407 sc->sc_copyfromdesc = lance_copyfrombuf_contig;
408 sc->sc_copytobuf = lance_copytobuf_contig;
409 sc->sc_copyfrombuf = lance_copyfrombuf_contig;
410 sc->sc_zerobuf = lance_zerobuf_contig;
411
412 sc->sc_rdcsr = le_pci_rdcsr;
413 sc->sc_wrcsr = le_pci_wrcsr;
414 sc->sc_hwreset = le_pci_hwreset;
395 switch (pci_get_device(dev)) {
396 case AMD_PCNET_HOME:
397 sc->sc_mediachange = le_pci_mediachange;
398 sc->sc_supmedia = le_home_supmedia;
399 sc->sc_nsupmedia = sizeof(le_home_supmedia) / sizeof(int);
400 sc->sc_defaultmedia = le_home_supmedia[0];
401 break;
402 default:
403 sc->sc_mediachange = le_pci_mediachange;
404 sc->sc_supmedia = le_pci_supmedia;
405 sc->sc_nsupmedia = sizeof(le_pci_supmedia) / sizeof(int);
406 sc->sc_defaultmedia = le_pci_supmedia[0];
407 }
408
409 /*
410 * Extract the physical MAC address from the ROM.
411 */
412 for (i = 0; i < sizeof(sc->sc_enaddr); i++)
413 sc->sc_enaddr[i] =
414 bus_space_read_1(lesc->sc_regt, lesc->sc_regh, i);
415
416 sc->sc_copytodesc = lance_copytobuf_contig;
417 sc->sc_copyfromdesc = lance_copyfrombuf_contig;
418 sc->sc_copytobuf = lance_copytobuf_contig;
419 sc->sc_copyfrombuf = lance_copyfrombuf_contig;
420 sc->sc_zerobuf = lance_zerobuf_contig;
421
422 sc->sc_rdcsr = le_pci_rdcsr;
423 sc->sc_wrcsr = le_pci_wrcsr;
424 sc->sc_hwreset = le_pci_hwreset;
425 sc->sc_hwinit = NULL;
426 sc->sc_hwintr = NULL;
427 sc->sc_nocarrier = NULL;
415
416 error = am79900_config(&lesc->sc_am79900, device_get_name(dev),
417 device_get_unit(dev));
418 if (error != 0) {
428
429 error = am79900_config(&lesc->sc_am79900, device_get_name(dev),
430 device_get_unit(dev));
431 if (error != 0) {
419 device_printf(dev, "cannot attach AM79900\n");
432 device_printf(dev, "cannot attach Am79900\n");
420 goto fail_dmap;
421 }
422
423 error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE,
424 am79900_intr, sc, &lesc->sc_ih);
425 if (error != 0) {
426 device_printf(dev, "cannot set up interrupt\n");
427 goto fail_am79900;
428 }
429
430 return (0);
431
432 fail_am79900:
433 am79900_detach(&lesc->sc_am79900);
434 fail_dmap:
435 bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam);
436 fail_dmem:
437 bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
438 fail_dtag:
439 bus_dma_tag_destroy(lesc->sc_dmat);
440 fail_pdtag:
441 bus_dma_tag_destroy(lesc->sc_pdmat);
442 fail_ires:
443 bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
444 fail_rres:
445 bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres);
446 fail_mtx:
447 LE_LOCK_DESTROY(sc);
448 return (error);
449}
450
451static int
452le_pci_detach(device_t dev)
453{
454 struct le_pci_softc *lesc;
455 struct lance_softc *sc;
456
457 lesc = device_get_softc(dev);
458 sc = &lesc->sc_am79900.lsc;
459
460 bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih);
461 am79900_detach(&lesc->sc_am79900);
462 bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam);
463 bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
464 bus_dma_tag_destroy(lesc->sc_dmat);
465 bus_dma_tag_destroy(lesc->sc_pdmat);
466 bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
467 bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres);
468 LE_LOCK_DESTROY(sc);
469
470 return (0);
471}
472
473static int
474le_pci_suspend(device_t dev)
475{
476 struct le_pci_softc *lesc;
477
478 lesc = device_get_softc(dev);
479
480 lance_suspend(&lesc->sc_am79900.lsc);
481
482 return (0);
483}
484
485static int
486le_pci_resume(device_t dev)
487{
488 struct le_pci_softc *lesc;
489
490 lesc = device_get_softc(dev);
491
492 lance_resume(&lesc->sc_am79900.lsc);
493
494 return (0);
495}
433 goto fail_dmap;
434 }
435
436 error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE,
437 am79900_intr, sc, &lesc->sc_ih);
438 if (error != 0) {
439 device_printf(dev, "cannot set up interrupt\n");
440 goto fail_am79900;
441 }
442
443 return (0);
444
445 fail_am79900:
446 am79900_detach(&lesc->sc_am79900);
447 fail_dmap:
448 bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam);
449 fail_dmem:
450 bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
451 fail_dtag:
452 bus_dma_tag_destroy(lesc->sc_dmat);
453 fail_pdtag:
454 bus_dma_tag_destroy(lesc->sc_pdmat);
455 fail_ires:
456 bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
457 fail_rres:
458 bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres);
459 fail_mtx:
460 LE_LOCK_DESTROY(sc);
461 return (error);
462}
463
464static int
465le_pci_detach(device_t dev)
466{
467 struct le_pci_softc *lesc;
468 struct lance_softc *sc;
469
470 lesc = device_get_softc(dev);
471 sc = &lesc->sc_am79900.lsc;
472
473 bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih);
474 am79900_detach(&lesc->sc_am79900);
475 bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam);
476 bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
477 bus_dma_tag_destroy(lesc->sc_dmat);
478 bus_dma_tag_destroy(lesc->sc_pdmat);
479 bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
480 bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres);
481 LE_LOCK_DESTROY(sc);
482
483 return (0);
484}
485
486static int
487le_pci_suspend(device_t dev)
488{
489 struct le_pci_softc *lesc;
490
491 lesc = device_get_softc(dev);
492
493 lance_suspend(&lesc->sc_am79900.lsc);
494
495 return (0);
496}
497
498static int
499le_pci_resume(device_t dev)
500{
501 struct le_pci_softc *lesc;
502
503 lesc = device_get_softc(dev);
504
505 lance_resume(&lesc->sc_am79900.lsc);
506
507 return (0);
508}