| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $Id: if_ae.c,v 1.11 2008/01/23 05:24:28 dyoung Exp $ */ | | 1 | /* $Id: if_ae.c,v 1.12 2008/03/11 23:19:03 dyoung Exp $ */ |
2 | /*- | | 2 | /*- |
3 | * Copyright (c) 2006 Urbana-Champaign Independent Media Center. | | 3 | * Copyright (c) 2006 Urbana-Champaign Independent Media Center. |
4 | * Copyright (c) 2006 Garrett D'Amore. | | 4 | * Copyright (c) 2006 Garrett D'Amore. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code was written by Garrett D'Amore for the Champaign-Urbana | | 7 | * This code was written by Garrett D'Amore for the Champaign-Urbana |
8 | * Community Wireless Network Project. | | 8 | * Community Wireless Network Project. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or | | 10 | * Redistribution and use in source and binary forms, with or |
11 | * without modification, are permitted provided that the following | | 11 | * without modification, are permitted provided that the following |
12 | * conditions are met: | | 12 | * conditions are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -95,27 +95,27 @@ | | | @@ -95,27 +95,27 @@ |
95 | * | | 95 | * |
96 | * 1) Find out about BUS_MODE_ALIGN16B. This chip can apparently align | | 96 | * 1) Find out about BUS_MODE_ALIGN16B. This chip can apparently align |
97 | * inbound packets on a half-word boundary, which would make life easier | | 97 | * inbound packets on a half-word boundary, which would make life easier |
98 | * for TCP/IP. (Aligning IP headers on a word.) | | 98 | * for TCP/IP. (Aligning IP headers on a word.) |
99 | * | | 99 | * |
100 | * 2) There is stuff in original tulip to shut down the device when reacting | | 100 | * 2) There is stuff in original tulip to shut down the device when reacting |
101 | * to a a change in link status. Is that needed. | | 101 | * to a a change in link status. Is that needed. |
102 | * | | 102 | * |
103 | * 3) Test with variety of 10/100 HDX/FDX scenarios. | | 103 | * 3) Test with variety of 10/100 HDX/FDX scenarios. |
104 | * | | 104 | * |
105 | */ | | 105 | */ |
106 | | | 106 | |
107 | #include <sys/cdefs.h> | | 107 | #include <sys/cdefs.h> |
108 | __KERNEL_RCSID(0, "$NetBSD: if_ae.c,v 1.11 2008/01/23 05:24:28 dyoung Exp $"); | | 108 | __KERNEL_RCSID(0, "$NetBSD: if_ae.c,v 1.12 2008/03/11 23:19:03 dyoung Exp $"); |
109 | | | 109 | |
110 | #include "bpfilter.h" | | 110 | #include "bpfilter.h" |
111 | | | 111 | |
112 | #include <sys/param.h> | | 112 | #include <sys/param.h> |
113 | #include <sys/systm.h> | | 113 | #include <sys/systm.h> |
114 | #include <sys/callout.h> | | 114 | #include <sys/callout.h> |
115 | #include <sys/mbuf.h> | | 115 | #include <sys/mbuf.h> |
116 | #include <sys/malloc.h> | | 116 | #include <sys/malloc.h> |
117 | #include <sys/kernel.h> | | 117 | #include <sys/kernel.h> |
118 | #include <sys/socket.h> | | 118 | #include <sys/socket.h> |
119 | #include <sys/ioctl.h> | | 119 | #include <sys/ioctl.h> |
120 | #include <sys/errno.h> | | 120 | #include <sys/errno.h> |
121 | #include <sys/device.h> | | 121 | #include <sys/device.h> |
| @@ -146,103 +146,103 @@ __KERNEL_RCSID(0, "$NetBSD: if_ae.c,v 1. | | | @@ -146,103 +146,103 @@ __KERNEL_RCSID(0, "$NetBSD: if_ae.c,v 1. |
146 | | | 146 | |
147 | static const struct { | | 147 | static const struct { |
148 | u_int32_t txth_opmode; /* OPMODE bits */ | | 148 | u_int32_t txth_opmode; /* OPMODE bits */ |
149 | const char *txth_name; /* name of mode */ | | 149 | const char *txth_name; /* name of mode */ |
150 | } ae_txthresh[] = { | | 150 | } ae_txthresh[] = { |
151 | { OPMODE_TR_32, "32 words" }, | | 151 | { OPMODE_TR_32, "32 words" }, |
152 | { OPMODE_TR_64, "64 words" }, | | 152 | { OPMODE_TR_64, "64 words" }, |
153 | { OPMODE_TR_128, "128 words" }, | | 153 | { OPMODE_TR_128, "128 words" }, |
154 | { OPMODE_TR_256, "256 words" }, | | 154 | { OPMODE_TR_256, "256 words" }, |
155 | { OPMODE_SF, "store and forward mode" }, | | 155 | { OPMODE_SF, "store and forward mode" }, |
156 | { 0, NULL }, | | 156 | { 0, NULL }, |
157 | }; | | 157 | }; |
158 | | | 158 | |
159 | static int ae_match(struct device *, struct cfdata *, void *); | | 159 | static int ae_match(device_t, struct cfdata *, void *); |
160 | static void ae_attach(struct device *, struct device *, void *); | | 160 | static void ae_attach(device_t, device_t, void *); |
161 | static int ae_detach(struct device *, int); | | 161 | static int ae_detach(device_t, int); |
162 | static int ae_activate(struct device *, enum devact); | | 162 | static int ae_activate(device_t, enum devact); |
163 | | | 163 | |
164 | static void ae_reset(struct ae_softc *); | | 164 | static void ae_reset(struct ae_softc *); |
165 | static void ae_idle(struct ae_softc *, u_int32_t); | | 165 | static void ae_idle(struct ae_softc *, u_int32_t); |
166 | | | 166 | |
167 | static void ae_start(struct ifnet *); | | 167 | static void ae_start(struct ifnet *); |
168 | static void ae_watchdog(struct ifnet *); | | 168 | static void ae_watchdog(struct ifnet *); |
169 | static int ae_ioctl(struct ifnet *, u_long, void *); | | 169 | static int ae_ioctl(struct ifnet *, u_long, void *); |
170 | static int ae_init(struct ifnet *); | | 170 | static int ae_init(struct ifnet *); |
171 | static void ae_stop(struct ifnet *, int); | | 171 | static void ae_stop(struct ifnet *, int); |
172 | | | 172 | |
173 | static void ae_shutdown(void *); | | 173 | static void ae_shutdown(void *); |
174 | | | 174 | |
175 | static void ae_rxdrain(struct ae_softc *); | | 175 | static void ae_rxdrain(struct ae_softc *); |
176 | static int ae_add_rxbuf(struct ae_softc *, int); | | 176 | static int ae_add_rxbuf(struct ae_softc *, int); |
177 | | | 177 | |
178 | static int ae_enable(struct ae_softc *); | | 178 | static int ae_enable(struct ae_softc *); |
179 | static void ae_disable(struct ae_softc *); | | 179 | static void ae_disable(struct ae_softc *); |
180 | static void ae_power(int, void *); | | 180 | static void ae_power(int, void *); |
181 | | | 181 | |
182 | static void ae_filter_setup(struct ae_softc *); | | 182 | static void ae_filter_setup(struct ae_softc *); |
183 | | | 183 | |
184 | static int ae_intr(void *); | | 184 | static int ae_intr(void *); |
185 | static void ae_rxintr(struct ae_softc *); | | 185 | static void ae_rxintr(struct ae_softc *); |
186 | static void ae_txintr(struct ae_softc *); | | 186 | static void ae_txintr(struct ae_softc *); |
187 | | | 187 | |
188 | static void ae_mii_tick(void *); | | 188 | static void ae_mii_tick(void *); |
189 | static void ae_mii_statchg(struct device *); | | 189 | static void ae_mii_statchg(device_t); |
190 | | | 190 | |
191 | static int ae_mii_readreg(struct device *, int, int); | | 191 | static int ae_mii_readreg(device_t, int, int); |
192 | static void ae_mii_writereg(struct device *, int, int, int); | | 192 | static void ae_mii_writereg(device_t, int, int, int); |
193 | | | 193 | |
194 | #ifdef AE_DEBUG | | 194 | #ifdef AE_DEBUG |
195 | #define DPRINTF(sc, x) if ((sc)->sc_ethercom.ec_if.if_flags & IFF_DEBUG) \ | | 195 | #define DPRINTF(sc, x) if ((sc)->sc_ethercom.ec_if.if_flags & IFF_DEBUG) \ |
196 | printf x | | 196 | printf x |
197 | #else | | 197 | #else |
198 | #define DPRINTF(sc, x) /* nothing */ | | 198 | #define DPRINTF(sc, x) /* nothing */ |
199 | #endif | | 199 | #endif |
200 | | | 200 | |
201 | #ifdef AE_STATS | | 201 | #ifdef AE_STATS |
202 | static void ae_print_stats(struct ae_softc *); | | 202 | static void ae_print_stats(struct ae_softc *); |
203 | #endif | | 203 | #endif |
204 | | | 204 | |
205 | CFATTACH_DECL(ae, sizeof(struct ae_softc), | | 205 | CFATTACH_DECL(ae, sizeof(struct ae_softc), |
206 | ae_match, ae_attach, ae_detach, ae_activate); | | 206 | ae_match, ae_attach, ae_detach, ae_activate); |
207 | | | 207 | |
208 | /* | | 208 | /* |
209 | * ae_match: | | 209 | * ae_match: |
210 | * | | 210 | * |
211 | * Check for a device match. | | 211 | * Check for a device match. |
212 | */ | | 212 | */ |
213 | int | | 213 | int |
214 | ae_match(struct device *parent, struct cfdata *cf, void *aux) | | 214 | ae_match(device_t parent, struct cfdata *cf, void *aux) |
215 | { | | 215 | { |
216 | struct arbus_attach_args *aa = aux; | | 216 | struct arbus_attach_args *aa = aux; |
217 | | | 217 | |
218 | if (strcmp(aa->aa_name, cf->cf_name) == 0) | | 218 | if (strcmp(aa->aa_name, cf->cf_name) == 0) |
219 | return 1; | | 219 | return 1; |
220 | | | 220 | |
221 | return 0; | | 221 | return 0; |
222 | | | 222 | |
223 | } | | 223 | } |
224 | | | 224 | |
225 | /* | | 225 | /* |
226 | * ae_attach: | | 226 | * ae_attach: |
227 | * | | 227 | * |
228 | * Attach an ae interface to the system. | | 228 | * Attach an ae interface to the system. |
229 | */ | | 229 | */ |
230 | void | | 230 | void |
231 | ae_attach(struct device *parent, struct device *self, void *aux) | | 231 | ae_attach(device_t parent, device_t self, void *aux) |
232 | { | | 232 | { |
233 | const uint8_t *enaddr; | | 233 | const uint8_t *enaddr; |
234 | prop_data_t ea; | | 234 | prop_data_t ea; |
235 | struct ae_softc *sc = (void *)self; | | 235 | struct ae_softc *sc = device_private(self); |
236 | struct arbus_attach_args *aa = aux; | | 236 | struct arbus_attach_args *aa = aux; |
237 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 237 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
238 | int i, error; | | 238 | int i, error; |
239 | | | 239 | |
240 | callout_init(&sc->sc_tick_callout, 0); | | 240 | callout_init(&sc->sc_tick_callout, 0); |
241 | | | 241 | |
242 | printf(": Atheros AR531X 10/100 Ethernet\n"); | | 242 | printf(": Atheros AR531X 10/100 Ethernet\n"); |
243 | | | 243 | |
244 | /* | | 244 | /* |
245 | * Try to get MAC address. | | 245 | * Try to get MAC address. |
246 | */ | | 246 | */ |
247 | ea = prop_dictionary_get(device_properties(&sc->sc_dev), "mac-addr"); | | 247 | ea = prop_dictionary_get(device_properties(&sc->sc_dev), "mac-addr"); |
248 | if (ea == NULL) { | | 248 | if (ea == NULL) { |
| @@ -445,56 +445,56 @@ ae_attach(struct device *parent, struct | | | @@ -445,56 +445,56 @@ ae_attach(struct device *parent, struct |
445 | bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg); | | 445 | bus_dmamem_free(sc->sc_dmat, &sc->sc_cdseg, sc->sc_cdnseg); |
446 | fail_1: | | 446 | fail_1: |
447 | bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_size); | | 447 | bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_size); |
448 | fail_0: | | 448 | fail_0: |
449 | return; | | 449 | return; |
450 | } | | 450 | } |
451 | | | 451 | |
452 | /* | | 452 | /* |
453 | * ae_activate: | | 453 | * ae_activate: |
454 | * | | 454 | * |
455 | * Handle device activation/deactivation requests. | | 455 | * Handle device activation/deactivation requests. |
456 | */ | | 456 | */ |
457 | int | | 457 | int |
458 | ae_activate(struct device *self, enum devact act) | | 458 | ae_activate(device_t self, enum devact act) |
459 | { | | 459 | { |
460 | struct ae_softc *sc = (void *) self; | | 460 | struct ae_softc *sc = device_private(self); |
461 | int s, error = 0; | | 461 | int s, error = 0; |
462 | | | 462 | |
463 | s = splnet(); | | 463 | s = splnet(); |
464 | switch (act) { | | 464 | switch (act) { |
465 | case DVACT_ACTIVATE: | | 465 | case DVACT_ACTIVATE: |
466 | error = EOPNOTSUPP; | | 466 | error = EOPNOTSUPP; |
467 | break; | | 467 | break; |
468 | | | 468 | |
469 | case DVACT_DEACTIVATE: | | 469 | case DVACT_DEACTIVATE: |
470 | mii_activate(&sc->sc_mii, act, MII_PHY_ANY, MII_OFFSET_ANY); | | 470 | mii_activate(&sc->sc_mii, act, MII_PHY_ANY, MII_OFFSET_ANY); |
471 | if_deactivate(&sc->sc_ethercom.ec_if); | | 471 | if_deactivate(&sc->sc_ethercom.ec_if); |
472 | break; | | 472 | break; |
473 | } | | 473 | } |
474 | splx(s); | | 474 | splx(s); |
475 | | | 475 | |
476 | return (error); | | 476 | return (error); |
477 | } | | 477 | } |
478 | | | 478 | |
479 | /* | | 479 | /* |
480 | * ae_detach: | | 480 | * ae_detach: |
481 | * | | 481 | * |
482 | * Detach a device interface. | | 482 | * Detach a device interface. |
483 | */ | | 483 | */ |
484 | int | | 484 | int |
485 | ae_detach(struct device *self, int flags) | | 485 | ae_detach(device_t self, int flags) |
486 | { | | 486 | { |
487 | struct ae_softc *sc = (void *)self; | | 487 | struct ae_softc *sc = device_private(self); |
488 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 488 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
489 | struct ae_rxsoft *rxs; | | 489 | struct ae_rxsoft *rxs; |
490 | struct ae_txsoft *txs; | | 490 | struct ae_txsoft *txs; |
491 | int i; | | 491 | int i; |
492 | | | 492 | |
493 | /* | | 493 | /* |
494 | * Succeed now if there isn't any work to do. | | 494 | * Succeed now if there isn't any work to do. |
495 | */ | | 495 | */ |
496 | if ((sc->sc_flags & AE_ATTACHED) == 0) | | 496 | if ((sc->sc_flags & AE_ATTACHED) == 0) |
497 | return (0); | | 497 | return (0); |
498 | | | 498 | |
499 | /* Unhook our tick handler. */ | | 499 | /* Unhook our tick handler. */ |
500 | if (sc->sc_tick) | | 500 | if (sc->sc_tick) |
| @@ -1862,29 +1862,29 @@ ae_mii_tick(void *arg) | | | @@ -1862,29 +1862,29 @@ ae_mii_tick(void *arg) |
1862 | s = splnet(); | | 1862 | s = splnet(); |
1863 | mii_tick(&sc->sc_mii); | | 1863 | mii_tick(&sc->sc_mii); |
1864 | splx(s); | | 1864 | splx(s); |
1865 | | | 1865 | |
1866 | callout_reset(&sc->sc_tick_callout, hz, sc->sc_tick, sc); | | 1866 | callout_reset(&sc->sc_tick_callout, hz, sc->sc_tick, sc); |
1867 | } | | 1867 | } |
1868 | | | 1868 | |
1869 | /* | | 1869 | /* |
1870 | * ae_mii_statchg: [mii interface function] | | 1870 | * ae_mii_statchg: [mii interface function] |
1871 | * | | 1871 | * |
1872 | * Callback from PHY when media changes. | | 1872 | * Callback from PHY when media changes. |
1873 | */ | | 1873 | */ |
1874 | static void | | 1874 | static void |
1875 | ae_mii_statchg(struct device *self) | | 1875 | ae_mii_statchg(device_t self) |
1876 | { | | 1876 | { |
1877 | struct ae_softc *sc = (struct ae_softc *)self; | | 1877 | struct ae_softc *sc = device_private(self); |
1878 | uint32_t macctl, flowc; | | 1878 | uint32_t macctl, flowc; |
1879 | | | 1879 | |
1880 | //opmode = AE_READ(sc, CSR_OPMODE); | | 1880 | //opmode = AE_READ(sc, CSR_OPMODE); |
1881 | macctl = AE_READ(sc, CSR_MACCTL); | | 1881 | macctl = AE_READ(sc, CSR_MACCTL); |
1882 | | | 1882 | |
1883 | /* XXX: do we need to do this? */ | | 1883 | /* XXX: do we need to do this? */ |
1884 | /* Idle the transmit and receive processes. */ | | 1884 | /* Idle the transmit and receive processes. */ |
1885 | //ae_idle(sc, OPMODE_ST|OPMODE_SR); | | 1885 | //ae_idle(sc, OPMODE_ST|OPMODE_SR); |
1886 | | | 1886 | |
1887 | if (sc->sc_mii.mii_media_active & IFM_FDX) { | | 1887 | if (sc->sc_mii.mii_media_active & IFM_FDX) { |
1888 | flowc = FLOWC_FCE; | | 1888 | flowc = FLOWC_FCE; |
1889 | macctl &= ~MACCTL_DRO; | | 1889 | macctl &= ~MACCTL_DRO; |
1890 | macctl |= MACCTL_FDX; | | 1890 | macctl |= MACCTL_FDX; |
| @@ -1898,52 +1898,52 @@ ae_mii_statchg(struct device *self) | | | @@ -1898,52 +1898,52 @@ ae_mii_statchg(struct device *self) |
1898 | AE_WRITE(sc, CSR_MACCTL, macctl); | | 1898 | AE_WRITE(sc, CSR_MACCTL, macctl); |
1899 | | | 1899 | |
1900 | /* restore operational mode */ | | 1900 | /* restore operational mode */ |
1901 | //AE_WRITE(sc, CSR_OPMODE, opmode); | | 1901 | //AE_WRITE(sc, CSR_OPMODE, opmode); |
1902 | AE_BARRIER(sc); | | 1902 | AE_BARRIER(sc); |
1903 | } | | 1903 | } |
1904 | | | 1904 | |
1905 | /* | | 1905 | /* |
1906 | * ae_mii_readreg: | | 1906 | * ae_mii_readreg: |
1907 | * | | 1907 | * |
1908 | * Read a PHY register. | | 1908 | * Read a PHY register. |
1909 | */ | | 1909 | */ |
1910 | static int | | 1910 | static int |
1911 | ae_mii_readreg(struct device *self, int phy, int reg) | | 1911 | ae_mii_readreg(device_t self, int phy, int reg) |
1912 | { | | 1912 | { |
1913 | struct ae_softc *sc = (struct ae_softc *)self; | | 1913 | struct ae_softc *sc = device_private(self); |
1914 | uint32_t addr; | | 1914 | uint32_t addr; |
1915 | int i; | | 1915 | int i; |
1916 | | | 1916 | |
1917 | addr = (phy << MIIADDR_PHY_SHIFT) | (reg << MIIADDR_REG_SHIFT); | | 1917 | addr = (phy << MIIADDR_PHY_SHIFT) | (reg << MIIADDR_REG_SHIFT); |
1918 | AE_WRITE(sc, CSR_MIIADDR, addr); | | 1918 | AE_WRITE(sc, CSR_MIIADDR, addr); |
1919 | AE_BARRIER(sc); | | 1919 | AE_BARRIER(sc); |
1920 | for (i = 0; i < 100000000; i++) { | | 1920 | for (i = 0; i < 100000000; i++) { |
1921 | if ((AE_READ(sc, CSR_MIIADDR) & MIIADDR_BUSY) == 0) | | 1921 | if ((AE_READ(sc, CSR_MIIADDR) & MIIADDR_BUSY) == 0) |
1922 | break; | | 1922 | break; |
1923 | } | | 1923 | } |
1924 | | | 1924 | |
1925 | return (AE_READ(sc, CSR_MIIDATA) & 0xffff); | | 1925 | return (AE_READ(sc, CSR_MIIDATA) & 0xffff); |
1926 | } | | 1926 | } |
1927 | | | 1927 | |
1928 | /* | | 1928 | /* |
1929 | * ae_mii_writereg: | | 1929 | * ae_mii_writereg: |
1930 | * | | 1930 | * |
1931 | * Write a PHY register. | | 1931 | * Write a PHY register. |
1932 | */ | | 1932 | */ |
1933 | static void | | 1933 | static void |
1934 | ae_mii_writereg(struct device *self, int phy, int reg, int val) | | 1934 | ae_mii_writereg(device_t self, int phy, int reg, int val) |
1935 | { | | 1935 | { |
1936 | struct ae_softc *sc = (struct ae_softc *)self; | | 1936 | struct ae_softc *sc = device_private(self); |
1937 | uint32_t addr; | | 1937 | uint32_t addr; |
1938 | int i; | | 1938 | int i; |
1939 | | | 1939 | |
1940 | /* write the data register */ | | 1940 | /* write the data register */ |
1941 | AE_WRITE(sc, CSR_MIIDATA, val); | | 1941 | AE_WRITE(sc, CSR_MIIDATA, val); |
1942 | | | 1942 | |
1943 | /* write the address to latch it in */ | | 1943 | /* write the address to latch it in */ |
1944 | addr = (phy << MIIADDR_PHY_SHIFT) | (reg << MIIADDR_REG_SHIFT) | | | 1944 | addr = (phy << MIIADDR_PHY_SHIFT) | (reg << MIIADDR_REG_SHIFT) | |
1945 | MIIADDR_WRITE; | | 1945 | MIIADDR_WRITE; |
1946 | AE_WRITE(sc, CSR_MIIADDR, addr); | | 1946 | AE_WRITE(sc, CSR_MIIADDR, addr); |
1947 | AE_BARRIER(sc); | | 1947 | AE_BARRIER(sc); |
1948 | | | 1948 | |
1949 | for (i = 0; i < 100000000; i++) { | | 1949 | for (i = 0; i < 100000000; i++) { |