Deleted Added
full compact
if_en_pci.c (113506) if_en_pci.c (114018)
1/* $NetBSD: if_en_pci.c,v 1.1 1996/06/22 02:00:31 chuck Exp $ */
2
3/*
4 *
5 * Copyright (c) 1996 Charles D. Cranor and Washington University.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 17 unchanged lines hidden (view full) ---

26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
1/* $NetBSD: if_en_pci.c,v 1.1 1996/06/22 02:00:31 chuck Exp $ */
2
3/*
4 *
5 * Copyright (c) 1996 Charles D. Cranor and Washington University.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 17 unchanged lines hidden (view full) ---

26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 * $FreeBSD: head/sys/dev/en/if_en_pci.c 113506 2003-04-15 06:37:30Z mdodd $
34 * $FreeBSD: head/sys/dev/en/if_en_pci.c 114018 2003-04-25 16:14:03Z harti $
35 */
36
37/*
38 *
39 * i f _ e n _ p c i . c
40 *
41 * author: Chuck Cranor <chuck@ccrc.wustl.edu>
42 * started: spring, 1996.
43 *
44 * FreeBSD PCI glue for the eni155p card.
45 * thanks to Matt Thomas for figuring out FreeBSD vs NetBSD vs etc.. diffs.
46 */
35 */
36
37/*
38 *
39 * i f _ e n _ p c i . c
40 *
41 * author: Chuck Cranor <chuck@ccrc.wustl.edu>
42 * started: spring, 1996.
43 *
44 * FreeBSD PCI glue for the eni155p card.
45 * thanks to Matt Thomas for figuring out FreeBSD vs NetBSD vs etc.. diffs.
46 */
47
48#include <sys/param.h>
49#include <sys/kernel.h>
50#include <sys/systm.h>
51#include <sys/socket.h>
47#include <sys/param.h>
48#include <sys/kernel.h>
49#include <sys/systm.h>
50#include <sys/socket.h>
51#include <sys/sysctl.h>
52
53#include <sys/bus.h>
54#include <machine/bus.h>
55#include <sys/rman.h>
56#include <machine/resource.h>
57
52
53#include <sys/bus.h>
54#include <machine/bus.h>
55#include <sys/rman.h>
56#include <machine/resource.h>
57
58#include <vm/uma.h>
59
58#include <net/if.h>
60#include <net/if.h>
61#include <net/if_atm.h>
59
60#include <pci/pcivar.h>
61#include <pci/pcireg.h>
62
63#include <dev/en/midwayreg.h>
64#include <dev/en/midwayvar.h>
65
66/*
62
63#include <pci/pcivar.h>
64#include <pci/pcireg.h>
65
66#include <dev/en/midwayreg.h>
67#include <dev/en/midwayvar.h>
68
69/*
67 * prototypes
68 */
69
70static int en_pci_probe(device_t);
71static int en_pci_attach(device_t);
72static int en_pci_detach(device_t);
73static int en_pci_shutdown(device_t);
74
75/*
76 * local structures
77 */
70 * local structures
71 */
78
79struct en_pci_softc {
72struct en_pci_softc {
80 /* bus independent stuff */
81 struct en_softc esc; /* includes "device" structure */
73 /* bus independent stuff */
74 struct en_softc esc; /* includes "device" structure */
82
75
83 /* freebsd newbus glue */
84 struct resource *res; /* resource descriptor for registers */
85 struct resource *irq; /* resource descriptor for interrupt */
86 void *ih; /* interrupt handle */
76 /* freebsd newbus glue */
77 struct resource *res; /* resource descriptor for registers */
78 struct resource *irq; /* resource descriptor for interrupt */
79 void *ih; /* interrupt handle */
87};
88
80};
81
89#if !defined(MIDWAY_ENIONLY)
90static void eni_get_macaddr(device_t, struct en_pci_softc *);
82static void eni_get_macaddr(device_t, struct en_pci_softc *);
91#endif
92#if !defined(MIDWAY_ADPONLY)
93static void adp_get_macaddr(struct en_pci_softc *);
83static void adp_get_macaddr(struct en_pci_softc *);
94#endif
95
84
96/*
97 * local defines (PCI specific stuff)
98 */
99
100/*
101 * address of config base memory address register in PCI config space
102 * (this is card specific)
103 */
85/*
86 * address of config base memory address register in PCI config space
87 * (this is card specific)
88 */
104
105#define PCI_CBMA 0x10
106
107/*
108 * tonga (pci bridge). ENI cards only!
109 */
89#define PCI_CBMA 0x10
90
91/*
92 * tonga (pci bridge). ENI cards only!
93 */
110
111#define EN_TONGA 0x60 /* PCI config addr of tonga reg */
112
113#define TONGA_SWAP_DMA 0x80 /* endian swap control */
114#define TONGA_SWAP_BYTE 0x40
115#define TONGA_SWAP_WORD 0x20
94#define EN_TONGA 0x60 /* PCI config addr of tonga reg */
95
96#define TONGA_SWAP_DMA 0x80 /* endian swap control */
97#define TONGA_SWAP_BYTE 0x40
98#define TONGA_SWAP_WORD 0x20
99#define TONGA_READ_MULT 0x00
100#define TONGA_READ_MEM 0x04
101#define TONGA_READ_IVAN 0x08
102#define TONGA_READ_KEN 0x0C
116
117/*
118 * adaptec pci bridge. ADP cards only!
119 */
103
104/*
105 * adaptec pci bridge. ADP cards only!
106 */
120
121#define ADP_PCIREG 0x050040 /* PCI control register */
122
123#define ADP_PCIREG_RESET 0x1 /* reset card */
124#define ADP_PCIREG_IENABLE 0x2 /* interrupt enable */
125#define ADP_PCIREG_SWAP_WORD 0x4 /* swap byte on slave access */
126#define ADP_PCIREG_SWAP_DMA 0x8 /* swap byte on DMA */
127
128#define PCI_VENDOR_EFFICIENTNETS 0x111a /* Efficent Networks */
129#define PCI_PRODUCT_EFFICIENTNETS_ENI155PF 0x0000 /* ENI-155P ATM */
130#define PCI_PRODUCT_EFFICIENTNETS_ENI155PA 0x0002 /* ENI-155P ATM */
131#define PCI_VENDOR_ADP 0x9004 /* adaptec */
132#define PCI_PRODUCT_ADP_AIC5900 0x5900
133#define PCI_PRODUCT_ADP_AIC5905 0x5905
134#define PCI_VENDOR(x) ((x) & 0xFFFF)
135#define PCI_CHIPID(x) (((x) >> 16) & 0xFFFF)
136
107#define ADP_PCIREG 0x050040 /* PCI control register */
108
109#define ADP_PCIREG_RESET 0x1 /* reset card */
110#define ADP_PCIREG_IENABLE 0x2 /* interrupt enable */
111#define ADP_PCIREG_SWAP_WORD 0x4 /* swap byte on slave access */
112#define ADP_PCIREG_SWAP_DMA 0x8 /* swap byte on DMA */
113
114#define PCI_VENDOR_EFFICIENTNETS 0x111a /* Efficent Networks */
115#define PCI_PRODUCT_EFFICIENTNETS_ENI155PF 0x0000 /* ENI-155P ATM */
116#define PCI_PRODUCT_EFFICIENTNETS_ENI155PA 0x0002 /* ENI-155P ATM */
117#define PCI_VENDOR_ADP 0x9004 /* adaptec */
118#define PCI_PRODUCT_ADP_AIC5900 0x5900
119#define PCI_PRODUCT_ADP_AIC5905 0x5905
120#define PCI_VENDOR(x) ((x) & 0xFFFF)
121#define PCI_CHIPID(x) (((x) >> 16) & 0xFFFF)
122
137#if !defined(MIDWAY_ENIONLY)
138
139static void adp_busreset(void *);
140
141/*
142 * bus specific reset function [ADP only!]
143 */
123/*
124 * bus specific reset function [ADP only!]
125 */
144
145static void adp_busreset(v)
146
147void *v;
148
126static void
127adp_busreset(void *v)
149{
128{
150 struct en_softc *sc = (struct en_softc *) v;
151 u_int32_t dummy;
129 struct en_softc *sc = (struct en_softc *)v;
130 uint32_t dummy;
152
131
153 bus_space_write_4(sc->en_memt, sc->en_base, ADP_PCIREG, ADP_PCIREG_RESET);
154 DELAY(1000); /* let it reset */
155 dummy = bus_space_read_4(sc->en_memt, sc->en_base, ADP_PCIREG);
156 bus_space_write_4(sc->en_memt, sc->en_base, ADP_PCIREG,
157 (ADP_PCIREG_SWAP_WORD|ADP_PCIREG_SWAP_DMA|ADP_PCIREG_IENABLE));
158 dummy = bus_space_read_4(sc->en_memt, sc->en_base, ADP_PCIREG);
159 if ((dummy & (ADP_PCIREG_SWAP_WORD|ADP_PCIREG_SWAP_DMA)) !=
160 (ADP_PCIREG_SWAP_WORD|ADP_PCIREG_SWAP_DMA))
161 printf("adp_busreset: Adaptec ATM did NOT reset!\n");
132 bus_space_write_4(sc->en_memt, sc->en_base, ADP_PCIREG,
133 ADP_PCIREG_RESET);
134 DELAY(1000); /* let it reset */
135 dummy = bus_space_read_4(sc->en_memt, sc->en_base, ADP_PCIREG);
136 bus_space_write_4(sc->en_memt, sc->en_base, ADP_PCIREG,
137 (ADP_PCIREG_SWAP_DMA | ADP_PCIREG_IENABLE));
138 dummy = bus_space_read_4(sc->en_memt, sc->en_base, ADP_PCIREG);
139 if ((dummy & (ADP_PCIREG_SWAP_WORD | ADP_PCIREG_SWAP_DMA)) !=
140 ADP_PCIREG_SWAP_DMA)
141 if_printf(&sc->enif, "adp_busreset: Adaptec ATM did "
142 "NOT reset!\n");
162}
143}
163#endif
164
165/***********************************************************************/
166
167/*
168 * autoconfig stuff
169 */
144
145/***********************************************************************/
146
147/*
148 * autoconfig stuff
149 */
170
171static int
172en_pci_probe(device_t dev)
173{
150static int
151en_pci_probe(device_t dev)
152{
174 switch (pci_get_vendor(dev)) {
175#if !defined(MIDWAY_ADPONLY)
176 case PCI_VENDOR_EFFICIENTNETS:
177 switch (pci_get_device(dev)) {
178 case PCI_PRODUCT_EFFICIENTNETS_ENI155PF:
179 case PCI_PRODUCT_EFFICIENTNETS_ENI155PA:
180 device_set_desc(dev, "Efficient Networks ENI-155p");
181 return 0;
182 }
183 break;
184#endif
185#if !defined(MIDWAY_ENIONLY)
186 case PCI_VENDOR_ADP:
187 switch (pci_get_device(dev)) {
188 case PCI_PRODUCT_ADP_AIC5900:
189 case PCI_PRODUCT_ADP_AIC5905:
190 device_set_desc(dev, "Adaptec 155 ATM");
191 return 0;
192 }
193 break;
194#endif
195 }
196 return ENXIO;
153 switch (pci_get_vendor(dev)) {
154
155 case PCI_VENDOR_EFFICIENTNETS:
156 switch (pci_get_device(dev)) {
157
158 case PCI_PRODUCT_EFFICIENTNETS_ENI155PF:
159 case PCI_PRODUCT_EFFICIENTNETS_ENI155PA:
160 device_set_desc(dev, "Efficient Networks ENI-155p");
161 return (0);
162 }
163 break;
164
165 case PCI_VENDOR_ADP:
166 switch (pci_get_device(dev)) {
167
168 case PCI_PRODUCT_ADP_AIC5900:
169 case PCI_PRODUCT_ADP_AIC5905:
170 device_set_desc(dev, "Adaptec 155 ATM");
171 return (0);
172 }
173 break;
174 }
175 return (ENXIO);
197}
198
199static int
200en_pci_attach(device_t dev)
201{
176}
177
178static int
179en_pci_attach(device_t dev)
180{
202 struct en_softc *sc;
203 struct en_pci_softc *scp;
204 u_long val;
205 int rid, s, unit, error = 0;
181 struct en_softc *sc;
182 struct en_pci_softc *scp;
183 u_long val;
184 int rid, unit, error = 0;
206
185
207 sc = device_get_softc(dev);
208 scp = (struct en_pci_softc *)sc;
209 bzero(scp, sizeof(*scp)); /* zero */
186 sc = device_get_softc(dev);
187 scp = (struct en_pci_softc *)sc;
210
188
211 s = splimp();
189 unit = device_get_unit(dev);
190 sc->enif.if_unit = unit;
191 sc->enif.if_name = "en";
212
192
213 /*
214 * Enable bus mastering.
215 */
216 val = pci_read_config(dev, PCIR_COMMAND, 2);
217 val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
218 pci_write_config(dev, PCIR_COMMAND, val, 2);
193 /*
194 * Enable bus mastering.
195 */
196 val = pci_read_config(dev, PCIR_COMMAND, 2);
197 val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN);
198 pci_write_config(dev, PCIR_COMMAND, val, 2);
219
199
220 /*
221 * Map control/status registers.
222 */
223 rid = PCI_CBMA;
224 scp->res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
225 0, ~0, 1, RF_ACTIVE);
226 if (!scp->res) {
227 device_printf(dev, "could not map memory\n");
228 error = ENXIO;
229 goto fail;
230 }
200 /*
201 * Map control/status registers.
202 */
203 rid = PCI_CBMA;
204 scp->res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
205 0, ~0, 1, RF_ACTIVE);
206 if (scp->res == NULL) {
207 device_printf(dev, "could not map memory\n");
208 error = ENXIO;
209 goto fail;
210 }
231
211
232 sc->en_memt = rman_get_bustag(scp->res);
233 sc->en_base = rman_get_bushandle(scp->res);
234
235 /*
236 * Allocate our interrupt.
237 */
238 rid = 0;
239 scp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
240 RF_SHAREABLE | RF_ACTIVE);
241 if (scp->irq == NULL) {
242 device_printf(dev, "could not map interrupt\n");
243 bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
244 error = ENXIO;
245 goto fail;
246 }
212 sc->dev = dev;
213 sc->en_memt = rman_get_bustag(scp->res);
214 sc->en_base = rman_get_bushandle(scp->res);
247
215
248 error = bus_setup_intr(dev, scp->irq, INTR_TYPE_NET,
249 en_intr, sc, &scp->ih);
250 if (error) {
251 device_printf(dev, "could not setup irq\n");
252 bus_release_resource(dev, SYS_RES_IRQ, 0, scp->irq);
253 bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
254 goto fail;
255 }
256 sc->ipl = 1; /* XXX (required to enable interrupt on midway) */
216 /*
217 * Allocate our interrupt.
218 */
219 rid = 0;
220 scp->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
221 RF_SHAREABLE | RF_ACTIVE);
222 if (scp->irq == NULL) {
223 device_printf(dev, "could not map interrupt\n");
224 bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
225 error = ENXIO;
226 goto fail;
227 }
257
228
258 unit = device_get_unit(dev);
259 snprintf(sc->sc_dev.dv_xname, sizeof(sc->sc_dev.dv_xname), "en%d", unit);
260 sc->enif.if_unit = unit;
261 sc->enif.if_name = "en";
229 sc->ipl = 1; /* XXX (required to enable interrupt on midway) */
262
230
263 /* figure out if we are an adaptec card or not */
264 sc->is_adaptec = (pci_get_vendor(dev) == PCI_VENDOR_ADP) ? 1 : 0;
265
266 /*
267 * set up pci bridge
268 */
269#if !defined(MIDWAY_ENIONLY)
270 if (sc->is_adaptec) {
271 adp_get_macaddr(scp);
272 sc->en_busreset = adp_busreset;
273 adp_busreset(sc);
274 }
275#endif
231 /* figure out if we are an adaptec card or not */
232 sc->is_adaptec = (pci_get_vendor(dev) == PCI_VENDOR_ADP) ? 1 : 0;
276
233
277#if !defined(MIDWAY_ADPONLY)
278 if (!sc->is_adaptec) {
279 eni_get_macaddr(dev, scp);
280 sc->en_busreset = NULL;
281 pci_write_config(dev, EN_TONGA, (TONGA_SWAP_DMA|TONGA_SWAP_WORD), 4);
282 }
283#endif
234 /*
235 * set up pci bridge
236 */
237 if (sc->is_adaptec) {
238 adp_get_macaddr(scp);
239 sc->en_busreset = adp_busreset;
240 adp_busreset(sc);
241 } else {
242 eni_get_macaddr(dev, scp);
243 sc->en_busreset = NULL;
244 pci_write_config(dev, EN_TONGA, TONGA_SWAP_DMA | TONGA_READ_IVAN, 4);
245 }
284
246
285 /*
286 * done PCI specific stuff
287 */
247 /*
248 * Common attach stuff
249 */
250 if ((error = en_attach(sc)) != 0) {
251 device_printf(dev, "attach failed\n");
252 bus_teardown_intr(dev, scp->irq, scp->ih);
253 bus_release_resource(dev, SYS_RES_IRQ, 0, scp->irq);
254 bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
255 goto fail;
256 }
288
257
289 en_attach(sc);
258 /*
259 * Do the interrupt SETUP last just before returning
260 */
261 error = bus_setup_intr(dev, scp->irq, INTR_TYPE_NET,
262 en_intr, sc, &scp->ih);
263 if (error) {
264 en_reset(sc);
265 if_detach(&sc->enif);
266 device_printf(dev, "could not setup irq\n");
267 bus_release_resource(dev, SYS_RES_IRQ, 0, scp->irq);
268 bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
269 en_destroy(sc);
270 goto fail;
271 }
290
272
291 splx(s);
273 return (0);
292
274
293 return 0;
294
295 fail:
296 splx(s);
297 return error;
275 fail:
276 return (error);
298}
299
277}
278
279/*
280 * Detach the adapter
281 */
300static int
301en_pci_detach(device_t dev)
302{
303 struct en_softc *sc = device_get_softc(dev);
304 struct en_pci_softc *scp = (struct en_pci_softc *)sc;
282static int
283en_pci_detach(device_t dev)
284{
285 struct en_softc *sc = device_get_softc(dev);
286 struct en_pci_softc *scp = (struct en_pci_softc *)sc;
305 int s;
306
287
307 s = splimp();
308
309 /*
288 /*
310 * Close down routes etc.
289 * Stop DMA and drop transmit queue.
311 */
290 */
312 if_detach(&sc->enif);
291 if ((sc->enif.if_flags & IFF_RUNNING)) {
292 if_printf(&sc->enif, "still running\n");
293 sc->enif.if_flags &= ~IFF_RUNNING;
294 }
313
314 /*
295
296 /*
315 * Stop DMA and drop transmit queue.
297 * Close down routes etc.
316 */
317 en_reset(sc);
298 */
299 en_reset(sc);
300 if_detach(&sc->enif);
318
319 /*
320 * Deallocate resources.
321 */
322 bus_teardown_intr(dev, scp->irq, scp->ih);
323 bus_release_resource(dev, SYS_RES_IRQ, 0, scp->irq);
324 bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
325
301
302 /*
303 * Deallocate resources.
304 */
305 bus_teardown_intr(dev, scp->irq, scp->ih);
306 bus_release_resource(dev, SYS_RES_IRQ, 0, scp->irq);
307 bus_release_resource(dev, SYS_RES_MEMORY, PCI_CBMA, scp->res);
308
326#ifdef notyet
327 /*
328 * Free all the driver internal resources
329 */
309 /*
310 * Free all the driver internal resources
311 */
330#endif
312 en_destroy(sc);
331
313
332 splx(s);
333
334 return 0;
314 return (0);
335}
336
337static int
338en_pci_shutdown(device_t dev)
339{
315}
316
317static int
318en_pci_shutdown(device_t dev)
319{
340 struct en_pci_softc *psc = (struct en_pci_softc *)device_get_softc(dev);
320 struct en_pci_softc *psc = device_get_softc(dev);
341
321
342 en_reset(&psc->esc);
343 DELAY(10); /* is this necessary? */
344 return (0);
322 en_reset(&psc->esc);
323 DELAY(10); /* is this necessary? */
324
325 return (0);
345}
346
326}
327
347#if !defined(MIDWAY_ENIONLY)
348
349#if defined(sparc)
350#define bus_space_read_1(t, h, o) \
351 ((void)t, (*(volatile u_int8_t *)((h) + (o))))
352#endif
353
328/*
329 * Get the MAC address from an Adaptec board. No idea how to get
330 * serial number or other stuff, because I have no documentation for that
331 * card.
332 */
354static void
333static void
355adp_get_macaddr(scp)
356 struct en_pci_softc *scp;
334adp_get_macaddr(struct en_pci_softc *scp)
357{
335{
358 struct en_softc * sc = (struct en_softc *)scp;
359 int lcv;
336 struct en_softc * sc = (struct en_softc *)scp;
337 int lcv;
360
338
361 for (lcv = 0; lcv < sizeof(sc->macaddr); lcv++)
362 sc->macaddr[lcv] = bus_space_read_1(sc->en_memt, sc->en_base,
363 MID_ADPMACOFF + lcv);
339 for (lcv = 0; lcv < sizeof(sc->macaddr); lcv++)
340 sc->macaddr[lcv] = bus_space_read_1(sc->en_memt, sc->en_base,
341 MID_ADPMACOFF + lcv);
364}
365
342}
343
366#endif /* MIDWAY_ENIONLY */
367
368#if !defined(MIDWAY_ADPONLY)
369
370/*
371 * Read station (MAC) address from serial EEPROM.
372 * derived from linux drivers/atm/eni.c by Werner Almesberger, EPFL LRC.
373 */
344/*
345 * Read station (MAC) address from serial EEPROM.
346 * derived from linux drivers/atm/eni.c by Werner Almesberger, EPFL LRC.
347 */
374#define EN_PROM_MAGIC 0x0c
375#define EN_PROM_DATA 0x02
376#define EN_PROM_CLK 0x01
377#define EN_ESI 64
348#define EN_PROM_MAGIC 0x0c
349#define EN_PROM_DATA 0x02
350#define EN_PROM_CLK 0x01
351#define EN_ESI 64
352#define EN_SERIAL 112
378
353
379static void
380eni_get_macaddr(device_t dev, struct en_pci_softc *scp)
354/*
355 * Read a byte from the given address in the EEPROM
356 */
357static uint8_t
358eni_get_byte(device_t dev, uint32_t *data, u_int address)
381{
359{
382 struct en_softc * sc = (struct en_softc *)scp;
383 int i, j, address, status;
384 u_int32_t data, t_data;
385 u_int8_t tmp;
386
387 t_data = pci_read_config(dev, EN_TONGA, 4) & 0xffffff00;
360 int j;
361 uint8_t tmp;
388
362
389 data = EN_PROM_MAGIC | EN_PROM_DATA | EN_PROM_CLK;
390 pci_write_config(dev, EN_TONGA, data, 4);
363 address = (address << 1) + 1;
391
364
392 for (i = 0; i < sizeof(sc->macaddr); i ++){
393 /* start operation */
394 data |= EN_PROM_DATA ;
395 pci_write_config(dev, EN_TONGA, data, 4);
396 data |= EN_PROM_CLK ;
397 pci_write_config(dev, EN_TONGA, data, 4);
398 data &= ~EN_PROM_DATA ;
399 pci_write_config(dev, EN_TONGA, data, 4);
400 data &= ~EN_PROM_CLK ;
401 pci_write_config(dev, EN_TONGA, data, 4);
402 /* send address with serial line */
403 address = ((i + EN_ESI) << 1) + 1;
404 for ( j = 7 ; j >= 0 ; j --){
405 data = (address >> j) & 1 ? data | EN_PROM_DATA :
406 data & ~EN_PROM_DATA;
407 pci_write_config(dev, EN_TONGA, data, 4);
408 data |= EN_PROM_CLK ;
409 pci_write_config(dev, EN_TONGA, data, 4);
410 data &= ~EN_PROM_CLK ;
411 pci_write_config(dev, EN_TONGA, data, 4);
412 }
413 /* get ack */
414 data |= EN_PROM_DATA ;
415 pci_write_config(dev, EN_TONGA, data, 4);
416 data |= EN_PROM_CLK ;
417 pci_write_config(dev, EN_TONGA, data, 4);
418 data = pci_read_config(dev, EN_TONGA, 4);
419 status = data & EN_PROM_DATA;
420 data &= ~EN_PROM_CLK ;
421 pci_write_config(dev, EN_TONGA, data, 4);
422 data |= EN_PROM_DATA ;
423 pci_write_config(dev, EN_TONGA, data, 4);
365 /* start operation */
366 *data |= EN_PROM_DATA ;
367 pci_write_config(dev, EN_TONGA, *data, 4);
368 *data |= EN_PROM_CLK ;
369 pci_write_config(dev, EN_TONGA, *data, 4);
370 *data &= ~EN_PROM_DATA ;
371 pci_write_config(dev, EN_TONGA, *data, 4);
372 *data &= ~EN_PROM_CLK ;
373 pci_write_config(dev, EN_TONGA, *data, 4);
374 /* send address with serial line */
375 for ( j = 7 ; j >= 0 ; j --) {
376 *data = ((address >> j) & 1) ? (*data | EN_PROM_DATA) :
377 (*data & ~EN_PROM_DATA);
378 pci_write_config(dev, EN_TONGA, *data, 4);
379 *data |= EN_PROM_CLK ;
380 pci_write_config(dev, EN_TONGA, *data, 4);
381 *data &= ~EN_PROM_CLK ;
382 pci_write_config(dev, EN_TONGA, *data, 4);
383 }
384 /* get ack */
385 *data |= EN_PROM_DATA ;
386 pci_write_config(dev, EN_TONGA, *data, 4);
387 *data |= EN_PROM_CLK ;
388 pci_write_config(dev, EN_TONGA, *data, 4);
389 *data = pci_read_config(dev, EN_TONGA, 4);
390 *data &= ~EN_PROM_CLK ;
391 pci_write_config(dev, EN_TONGA, *data, 4);
392 *data |= EN_PROM_DATA ;
393 pci_write_config(dev, EN_TONGA, *data, 4);
424
394
425 tmp = 0;
395 tmp = 0;
426
396
427 for ( j = 7 ; j >= 0 ; j --){
428 tmp <<= 1;
429 data |= EN_PROM_DATA ;
430 pci_write_config(dev, EN_TONGA, data, 4);
431 data |= EN_PROM_CLK ;
432 pci_write_config(dev, EN_TONGA, data, 4);
433 data = pci_read_config(dev, EN_TONGA, 4);
434 if(data & EN_PROM_DATA) tmp |= 1;
435 data &= ~EN_PROM_CLK ;
436 pci_write_config(dev, EN_TONGA, data, 4);
437 data |= EN_PROM_DATA ;
438 pci_write_config(dev, EN_TONGA, data, 4);
439 }
440 /* get ack */
441 data |= EN_PROM_DATA ;
442 pci_write_config(dev, EN_TONGA, data, 4);
443 data |= EN_PROM_CLK ;
444 pci_write_config(dev, EN_TONGA, data, 4);
445 data = pci_read_config(dev, EN_TONGA, 4);
446 status = data & EN_PROM_DATA;
447 data &= ~EN_PROM_CLK ;
448 pci_write_config(dev, EN_TONGA, data, 4);
449 data |= EN_PROM_DATA ;
450 pci_write_config(dev, EN_TONGA, data, 4);
397 for ( j = 7 ; j >= 0 ; j --) {
398 tmp <<= 1;
399 *data |= EN_PROM_DATA ;
400 pci_write_config(dev, EN_TONGA, *data, 4);
401 *data |= EN_PROM_CLK ;
402 pci_write_config(dev, EN_TONGA, *data, 4);
403 *data = pci_read_config(dev, EN_TONGA, 4);
404 if(*data & EN_PROM_DATA) tmp |= 1;
405 *data &= ~EN_PROM_CLK ;
406 pci_write_config(dev, EN_TONGA, *data, 4);
407 *data |= EN_PROM_DATA ;
408 pci_write_config(dev, EN_TONGA, *data, 4);
409 }
410 /* get ack */
411 *data |= EN_PROM_DATA ;
412 pci_write_config(dev, EN_TONGA, *data, 4);
413 *data |= EN_PROM_CLK ;
414 pci_write_config(dev, EN_TONGA, *data, 4);
415 *data = pci_read_config(dev, EN_TONGA, 4);
416 *data &= ~EN_PROM_CLK ;
417 pci_write_config(dev, EN_TONGA, *data, 4);
418 *data |= EN_PROM_DATA ;
419 pci_write_config(dev, EN_TONGA, *data, 4);
451
420
452 sc->macaddr[i] = tmp;
453 }
454 /* stop operation */
455 data &= ~EN_PROM_DATA;
456 pci_write_config(dev, EN_TONGA, data, 4);
457 data |= EN_PROM_CLK;
458 pci_write_config(dev, EN_TONGA, data, 4);
459 data |= EN_PROM_DATA;
460 pci_write_config(dev, EN_TONGA, data, 4);
461 pci_write_config(dev, EN_TONGA, t_data, 4);
421 return (tmp);
462}
463
422}
423
464#endif /* !MIDWAY_ADPONLY */
424/*
425 * Get MAC address and other stuff from the EEPROM
426 */
427static void
428eni_get_macaddr(device_t dev, struct en_pci_softc *scp)
429{
430 struct en_softc * sc = (struct en_softc *)scp;
431 int i;
432 uint32_t data, t_data;
465
433
434 t_data = pci_read_config(dev, EN_TONGA, 4) & 0xffffff00;
435
436 data = EN_PROM_MAGIC | EN_PROM_DATA | EN_PROM_CLK;
437 pci_write_config(dev, EN_TONGA, data, 4);
438
439 for (i = 0; i < sizeof(sc->macaddr); i ++)
440 sc->macaddr[i] = eni_get_byte(dev, &data, i + EN_ESI);
441
442 sc->serial = 0;
443 for (i = 0; i < 4; i++) {
444 sc->serial <<= 8;
445 sc->serial |= eni_get_byte(dev, &data, i + EN_SERIAL);
446 }
447 /* stop operation */
448 data &= ~EN_PROM_DATA;
449 pci_write_config(dev, EN_TONGA, data, 4);
450 data |= EN_PROM_CLK;
451 pci_write_config(dev, EN_TONGA, data, 4);
452 data |= EN_PROM_DATA;
453 pci_write_config(dev, EN_TONGA, data, 4);
454 pci_write_config(dev, EN_TONGA, t_data, 4);
455}
456
457/*
458 * Driver infrastructure
459 */
466static device_method_t en_methods[] = {
467 /* Device interface */
468 DEVMETHOD(device_probe, en_pci_probe),
469 DEVMETHOD(device_attach, en_pci_attach),
470 DEVMETHOD(device_detach, en_pci_detach),
471 DEVMETHOD(device_shutdown, en_pci_shutdown),
472
473 { 0, 0 }
474};
475
476static driver_t en_driver = {
477 "en",
478 en_methods,
479 sizeof(struct en_pci_softc),
480};
481
482static devclass_t en_devclass;
483
484DRIVER_MODULE(en, pci, en_driver, en_devclass, 0, 0);
460static device_method_t en_methods[] = {
461 /* Device interface */
462 DEVMETHOD(device_probe, en_pci_probe),
463 DEVMETHOD(device_attach, en_pci_attach),
464 DEVMETHOD(device_detach, en_pci_detach),
465 DEVMETHOD(device_shutdown, en_pci_shutdown),
466
467 { 0, 0 }
468};
469
470static driver_t en_driver = {
471 "en",
472 en_methods,
473 sizeof(struct en_pci_softc),
474};
475
476static devclass_t en_devclass;
477
478DRIVER_MODULE(en, pci, en_driver, en_devclass, 0, 0);
485