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 | |