| File: | dev/ic/dc.c |
| Warning: | line 744, column 3 3rd function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: dc.c,v 1.154 2020/07/10 13:26:37 patrick Exp $ */ | |||
| 2 | ||||
| 3 | /* | |||
| 4 | * Copyright (c) 1997, 1998, 1999 | |||
| 5 | * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved. | |||
| 6 | * | |||
| 7 | * Redistribution and use in source and binary forms, with or without | |||
| 8 | * modification, are permitted provided that the following conditions | |||
| 9 | * are met: | |||
| 10 | * 1. Redistributions of source code must retain the above copyright | |||
| 11 | * notice, this list of conditions and the following disclaimer. | |||
| 12 | * 2. Redistributions in binary form must reproduce the above copyright | |||
| 13 | * notice, this list of conditions and the following disclaimer in the | |||
| 14 | * documentation and/or other materials provided with the distribution. | |||
| 15 | * 3. All advertising materials mentioning features or use of this software | |||
| 16 | * must display the following acknowledgement: | |||
| 17 | * This product includes software developed by Bill Paul. | |||
| 18 | * 4. Neither the name of the author nor the names of any co-contributors | |||
| 19 | * may be used to endorse or promote products derived from this software | |||
| 20 | * without specific prior written permission. | |||
| 21 | * | |||
| 22 | * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND | |||
| 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
| 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
| 25 | * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD | |||
| 26 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |||
| 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |||
| 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |||
| 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |||
| 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |||
| 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | |||
| 32 | * THE POSSIBILITY OF SUCH DAMAGE. | |||
| 33 | * | |||
| 34 | * $FreeBSD: src/sys/pci/if_dc.c,v 1.43 2001/01/19 23:55:07 wpaul Exp $ | |||
| 35 | */ | |||
| 36 | ||||
| 37 | /* | |||
| 38 | * DEC "tulip" clone ethernet driver. Supports the DEC/Intel 21143 | |||
| 39 | * series chips and several workalikes including the following: | |||
| 40 | * | |||
| 41 | * Macronix 98713/98715/98725/98727/98732 PMAC (www.macronix.com) | |||
| 42 | * Macronix/Lite-On 82c115 PNIC II (www.macronix.com) | |||
| 43 | * Lite-On 82c168/82c169 PNIC (www.litecom.com) | |||
| 44 | * ASIX Electronics AX88140A (www.asix.com.tw) | |||
| 45 | * ASIX Electronics AX88141 (www.asix.com.tw) | |||
| 46 | * ADMtek AL981 (www.admtek.com.tw) | |||
| 47 | * ADMtek AN983 (www.admtek.com.tw) | |||
| 48 | * Davicom DM9100, DM9102, DM9102A (www.davicom8.com) | |||
| 49 | * Accton EN1217, EN2242 (www.accton.com) | |||
| 50 | * Xircom X3201 (www.xircom.com) | |||
| 51 | * | |||
| 52 | * Datasheets for the 21143 are available at developer.intel.com. | |||
| 53 | * Datasheets for the clone parts can be found at their respective sites. | |||
| 54 | * (Except for the PNIC; see www.freebsd.org/~wpaul/PNIC/pnic.ps.gz.) | |||
| 55 | * The PNIC II is essentially a Macronix 98715A chip; the only difference | |||
| 56 | * worth noting is that its multicast hash table is only 128 bits wide | |||
| 57 | * instead of 512. | |||
| 58 | * | |||
| 59 | * Written by Bill Paul <wpaul@ee.columbia.edu> | |||
| 60 | * Electrical Engineering Department | |||
| 61 | * Columbia University, New York City | |||
| 62 | */ | |||
| 63 | ||||
| 64 | /* | |||
| 65 | * The Intel 21143 is the successor to the DEC 21140. It is basically | |||
| 66 | * the same as the 21140 but with a few new features. The 21143 supports | |||
| 67 | * three kinds of media attachments: | |||
| 68 | * | |||
| 69 | * o MII port, for 10Mbps and 100Mbps support and NWAY | |||
| 70 | * autonegotiation provided by an external PHY. | |||
| 71 | * o SYM port, for symbol mode 100Mbps support. | |||
| 72 | * o 10baseT port. | |||
| 73 | * o AUI/BNC port. | |||
| 74 | * | |||
| 75 | * The 100Mbps SYM port and 10baseT port can be used together in | |||
| 76 | * combination with the internal NWAY support to create a 10/100 | |||
| 77 | * autosensing configuration. | |||
| 78 | * | |||
| 79 | * Note that not all tulip workalikes are handled in this driver: we only | |||
| 80 | * deal with those which are relatively well behaved. The Winbond is | |||
| 81 | * handled separately due to its different register offsets and the | |||
| 82 | * special handling needed for its various bugs. The PNIC is handled | |||
| 83 | * here, but I'm not thrilled about it. | |||
| 84 | * | |||
| 85 | * All of the workalike chips use some form of MII transceiver support | |||
| 86 | * with the exception of the Macronix chips, which also have a SYM port. | |||
| 87 | * The ASIX AX88140A is also documented to have a SYM port, but all | |||
| 88 | * the cards I've seen use an MII transceiver, probably because the | |||
| 89 | * AX88140A doesn't support internal NWAY. | |||
| 90 | */ | |||
| 91 | ||||
| 92 | #include "bpfilter.h" | |||
| 93 | ||||
| 94 | #include <sys/param.h> | |||
| 95 | #include <sys/systm.h> | |||
| 96 | #include <sys/mbuf.h> | |||
| 97 | #include <sys/protosw.h> | |||
| 98 | #include <sys/socket.h> | |||
| 99 | #include <sys/ioctl.h> | |||
| 100 | #include <sys/errno.h> | |||
| 101 | #include <sys/malloc.h> | |||
| 102 | #include <sys/kernel.h> | |||
| 103 | #include <sys/device.h> | |||
| 104 | #include <sys/timeout.h> | |||
| 105 | ||||
| 106 | #include <net/if.h> | |||
| 107 | ||||
| 108 | #include <netinet/in.h> | |||
| 109 | #include <netinet/if_ether.h> | |||
| 110 | ||||
| 111 | #include <net/if_media.h> | |||
| 112 | ||||
| 113 | #if NBPFILTER1 > 0 | |||
| 114 | #include <net/bpf.h> | |||
| 115 | #endif | |||
| 116 | ||||
| 117 | #include <dev/mii/mii.h> | |||
| 118 | #include <dev/mii/miivar.h> | |||
| 119 | ||||
| 120 | #include <machine/bus.h> | |||
| 121 | #include <dev/pci/pcidevs.h> | |||
| 122 | ||||
| 123 | #include <dev/ic/dcreg.h> | |||
| 124 | ||||
| 125 | /* | |||
| 126 | * The Davicom DM9102 has a broken DMA engine that reads beyond the | |||
| 127 | * end of the programmed transfer. Architectures with a proper IOMMU | |||
| 128 | * (such as sparc64) will trap on this access. To avoid having to | |||
| 129 | * copy each transmitted mbuf to guarantee enough trailing space, | |||
| 130 | * those architectures should implement BUS_DMA_OVERRUN that takes | |||
| 131 | * appropriate action to tolerate this behaviour. | |||
| 132 | */ | |||
| 133 | #ifndef BUS_DMA_OVERRUN0 | |||
| 134 | #define BUS_DMA_OVERRUN0 0 | |||
| 135 | #endif | |||
| 136 | ||||
| 137 | int dc_intr(void *); | |||
| 138 | struct dc_type *dc_devtype(void *); | |||
| 139 | int dc_newbuf(struct dc_softc *, int, struct mbuf *); | |||
| 140 | int dc_encap(struct dc_softc *, bus_dmamap_t, struct mbuf *, u_int32_t *); | |||
| 141 | ||||
| 142 | void dc_pnic_rx_bug_war(struct dc_softc *, int); | |||
| 143 | int dc_rx_resync(struct dc_softc *); | |||
| 144 | int dc_rxeof(struct dc_softc *); | |||
| 145 | void dc_txeof(struct dc_softc *); | |||
| 146 | void dc_tick(void *); | |||
| 147 | void dc_tx_underrun(struct dc_softc *); | |||
| 148 | void dc_start(struct ifnet *); | |||
| 149 | int dc_ioctl(struct ifnet *, u_long, caddr_t); | |||
| 150 | void dc_watchdog(struct ifnet *); | |||
| 151 | int dc_ifmedia_upd(struct ifnet *); | |||
| 152 | void dc_ifmedia_sts(struct ifnet *, struct ifmediareq *); | |||
| 153 | ||||
| 154 | void dc_delay(struct dc_softc *); | |||
| 155 | void dc_eeprom_width(struct dc_softc *); | |||
| 156 | void dc_eeprom_idle(struct dc_softc *); | |||
| 157 | void dc_eeprom_putbyte(struct dc_softc *, int); | |||
| 158 | void dc_eeprom_getword(struct dc_softc *, int, u_int16_t *); | |||
| 159 | void dc_eeprom_getword_pnic(struct dc_softc *, int, u_int16_t *); | |||
| 160 | void dc_eeprom_getword_xircom(struct dc_softc *, int, u_int16_t *); | |||
| 161 | void dc_read_eeprom(struct dc_softc *, caddr_t, int, int, int); | |||
| 162 | ||||
| 163 | void dc_mii_writebit(struct dc_softc *, int); | |||
| 164 | int dc_mii_readbit(struct dc_softc *); | |||
| 165 | void dc_mii_sync(struct dc_softc *); | |||
| 166 | void dc_mii_send(struct dc_softc *, u_int32_t, int); | |||
| 167 | int dc_mii_readreg(struct dc_softc *, struct dc_mii_frame *); | |||
| 168 | int dc_mii_writereg(struct dc_softc *, struct dc_mii_frame *); | |||
| 169 | int dc_miibus_readreg(struct device *, int, int); | |||
| 170 | void dc_miibus_writereg(struct device *, int, int, int); | |||
| 171 | void dc_miibus_statchg(struct device *); | |||
| 172 | ||||
| 173 | void dc_setcfg(struct dc_softc *, uint64_t); | |||
| 174 | u_int32_t dc_crc_le(struct dc_softc *, caddr_t); | |||
| 175 | u_int32_t dc_crc_be(caddr_t)((ether_crc32_be(caddr_t,6) >> 26) & 0x0000003F); | |||
| 176 | void dc_setfilt_21143(struct dc_softc *); | |||
| 177 | void dc_setfilt_asix(struct dc_softc *); | |||
| 178 | void dc_setfilt_admtek(struct dc_softc *); | |||
| 179 | void dc_setfilt_xircom(struct dc_softc *); | |||
| 180 | ||||
| 181 | void dc_setfilt(struct dc_softc *); | |||
| 182 | ||||
| 183 | void dc_reset(struct dc_softc *); | |||
| 184 | int dc_list_rx_init(struct dc_softc *); | |||
| 185 | int dc_list_tx_init(struct dc_softc *); | |||
| 186 | ||||
| 187 | void dc_read_srom(struct dc_softc *, int); | |||
| 188 | void dc_parse_21143_srom(struct dc_softc *); | |||
| 189 | void dc_decode_leaf_sia(struct dc_softc *, | |||
| 190 | struct dc_eblock_sia *); | |||
| 191 | void dc_decode_leaf_mii(struct dc_softc *, | |||
| 192 | struct dc_eblock_mii *); | |||
| 193 | void dc_decode_leaf_sym(struct dc_softc *, | |||
| 194 | struct dc_eblock_sym *); | |||
| 195 | void dc_apply_fixup(struct dc_softc *, uint64_t); | |||
| 196 | ||||
| 197 | #define DC_SETBIT(sc, reg, x)((sc->dc_btag)->write_4((sc->dc_bhandle), (reg), ((( sc->dc_btag)->read_4((sc->dc_bhandle), (reg))) | (x) ))) \ | |||
| 198 | CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) | (x))((sc->dc_btag)->write_4((sc->dc_bhandle), (reg), ((( sc->dc_btag)->read_4((sc->dc_bhandle), (reg))) | (x) ))) | |||
| 199 | ||||
| 200 | #define DC_CLRBIT(sc, reg, x)((sc->dc_btag)->write_4((sc->dc_bhandle), (reg), ((( sc->dc_btag)->read_4((sc->dc_bhandle), (reg))) & ~(x)))) \ | |||
| 201 | CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) & ~(x))((sc->dc_btag)->write_4((sc->dc_bhandle), (reg), ((( sc->dc_btag)->read_4((sc->dc_bhandle), (reg))) & ~(x)))) | |||
| 202 | ||||
| 203 | #define SIO_SET(x)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( (x))))) DC_SETBIT(sc, DC_SIO, (x))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( (x))))) | |||
| 204 | #define SIO_CLR(x)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~((x))))) DC_CLRBIT(sc, DC_SIO, (x))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~((x))))) | |||
| 205 | ||||
| 206 | void | |||
| 207 | dc_delay(struct dc_softc *sc) | |||
| 208 | { | |||
| 209 | int idx; | |||
| 210 | ||||
| 211 | for (idx = (300 / 33) + 1; idx > 0; idx--) | |||
| 212 | CSR_READ_4(sc, DC_BUSCTL)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x00))); | |||
| 213 | } | |||
| 214 | ||||
| 215 | void | |||
| 216 | dc_eeprom_width(struct dc_softc *sc) | |||
| 217 | { | |||
| 218 | int i; | |||
| 219 | ||||
| 220 | /* Force EEPROM to idle state. */ | |||
| 221 | dc_eeprom_idle(sc); | |||
| 222 | ||||
| 223 | /* Enter EEPROM access mode. */ | |||
| 224 | CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (0x00000800 ))); | |||
| 225 | dc_delay(sc); | |||
| 226 | DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00004000)))); | |||
| 227 | dc_delay(sc); | |||
| 228 | DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00000002)))); | |||
| 229 | dc_delay(sc); | |||
| 230 | DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00000001)))); | |||
| 231 | dc_delay(sc); | |||
| 232 | ||||
| 233 | for (i = 3; i--;) { | |||
| 234 | if (6 & (1 << i)) | |||
| 235 | DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00000004)))); | |||
| 236 | else | |||
| 237 | DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00000004)))); | |||
| 238 | dc_delay(sc); | |||
| 239 | DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00000002)))); | |||
| 240 | dc_delay(sc); | |||
| 241 | DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00000002)))); | |||
| 242 | dc_delay(sc); | |||
| 243 | } | |||
| 244 | ||||
| 245 | for (i = 1; i <= 12; i++) { | |||
| 246 | DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00000002)))); | |||
| 247 | dc_delay(sc); | |||
| 248 | if (!(CSR_READ_4(sc, DC_SIO)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & DC_SIO_EE_DATAOUT0x00000008)) { | |||
| 249 | DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00000002)))); | |||
| 250 | dc_delay(sc); | |||
| 251 | break; | |||
| 252 | } | |||
| 253 | DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00000002)))); | |||
| 254 | dc_delay(sc); | |||
| 255 | } | |||
| 256 | ||||
| 257 | /* Turn off EEPROM access mode. */ | |||
| 258 | dc_eeprom_idle(sc); | |||
| 259 | ||||
| 260 | if (i < 4 || i > 12) | |||
| 261 | sc->dc_romwidth = 6; | |||
| 262 | else | |||
| 263 | sc->dc_romwidth = i; | |||
| 264 | ||||
| 265 | /* Enter EEPROM access mode. */ | |||
| 266 | CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (0x00000800 ))); | |||
| 267 | dc_delay(sc); | |||
| 268 | DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00004000)))); | |||
| 269 | dc_delay(sc); | |||
| 270 | DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00000002)))); | |||
| 271 | dc_delay(sc); | |||
| 272 | DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00000001)))); | |||
| 273 | dc_delay(sc); | |||
| 274 | ||||
| 275 | /* Turn off EEPROM access mode. */ | |||
| 276 | dc_eeprom_idle(sc); | |||
| 277 | } | |||
| 278 | ||||
| 279 | void | |||
| 280 | dc_eeprom_idle(struct dc_softc *sc) | |||
| 281 | { | |||
| 282 | int i; | |||
| 283 | ||||
| 284 | CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (0x00000800 ))); | |||
| 285 | dc_delay(sc); | |||
| 286 | DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00004000)))); | |||
| 287 | dc_delay(sc); | |||
| 288 | DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00000002)))); | |||
| 289 | dc_delay(sc); | |||
| 290 | DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00000001)))); | |||
| 291 | dc_delay(sc); | |||
| 292 | ||||
| 293 | for (i = 0; i < 25; i++) { | |||
| 294 | DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00000002)))); | |||
| 295 | dc_delay(sc); | |||
| 296 | DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00000002)))); | |||
| 297 | dc_delay(sc); | |||
| 298 | } | |||
| 299 | ||||
| 300 | DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00000002)))); | |||
| 301 | dc_delay(sc); | |||
| 302 | DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CS)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00000001)))); | |||
| 303 | dc_delay(sc); | |||
| 304 | CSR_WRITE_4(sc, DC_SIO, 0x00000000)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (0x00000000 ))); | |||
| 305 | } | |||
| 306 | ||||
| 307 | /* | |||
| 308 | * Send a read command and address to the EEPROM, check for ACK. | |||
| 309 | */ | |||
| 310 | void | |||
| 311 | dc_eeprom_putbyte(struct dc_softc *sc, int addr) | |||
| 312 | { | |||
| 313 | int d, i; | |||
| 314 | ||||
| 315 | d = DC_EECMD_READ0x180 >> 6; | |||
| 316 | ||||
| 317 | for (i = 3; i--; ) { | |||
| 318 | if (d & (1 << i)) | |||
| 319 | DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00000004)))); | |||
| 320 | else | |||
| 321 | DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00000004)))); | |||
| 322 | dc_delay(sc); | |||
| 323 | DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00000002)))); | |||
| 324 | dc_delay(sc); | |||
| 325 | DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00000002)))); | |||
| 326 | dc_delay(sc); | |||
| 327 | } | |||
| 328 | ||||
| 329 | /* | |||
| 330 | * Feed in each bit and strobe the clock. | |||
| 331 | */ | |||
| 332 | for (i = sc->dc_romwidth; i--;) { | |||
| 333 | if (addr & (1 << i)) { | |||
| 334 | SIO_SET(DC_SIO_EE_DATAIN)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( (0x00000004))))); | |||
| 335 | } else { | |||
| 336 | SIO_CLR(DC_SIO_EE_DATAIN)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~((0x00000004))))); | |||
| 337 | } | |||
| 338 | dc_delay(sc); | |||
| 339 | SIO_SET(DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( (0x00000002))))); | |||
| 340 | dc_delay(sc); | |||
| 341 | SIO_CLR(DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~((0x00000002))))); | |||
| 342 | dc_delay(sc); | |||
| 343 | } | |||
| 344 | } | |||
| 345 | ||||
| 346 | /* | |||
| 347 | * Read a word of data stored in the EEPROM at address 'addr.' | |||
| 348 | * The PNIC 82c168/82c169 has its own non-standard way to read | |||
| 349 | * the EEPROM. | |||
| 350 | */ | |||
| 351 | void | |||
| 352 | dc_eeprom_getword_pnic(struct dc_softc *sc, int addr, u_int16_t *dest) | |||
| 353 | { | |||
| 354 | int i; | |||
| 355 | u_int32_t r; | |||
| 356 | ||||
| 357 | CSR_WRITE_4(sc, DC_PN_SIOCTL, DC_PN_EEOPCODE_READ|addr)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x98), (0x00000600 |addr))); | |||
| 358 | ||||
| 359 | for (i = 0; i < DC_TIMEOUT1000; i++) { | |||
| 360 | DELAY(1)(*delay_func)(1); | |||
| 361 | r = CSR_READ_4(sc, DC_SIO)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))); | |||
| 362 | if (!(r & DC_PN_SIOCTL_BUSY0x80000000)) { | |||
| 363 | *dest = (u_int16_t)(r & 0xFFFF); | |||
| 364 | return; | |||
| 365 | } | |||
| 366 | } | |||
| 367 | } | |||
| 368 | ||||
| 369 | /* | |||
| 370 | * Read a word of data stored in the EEPROM at address 'addr.' | |||
| 371 | * The Xircom X3201 has its own non-standard way to read | |||
| 372 | * the EEPROM, too. | |||
| 373 | */ | |||
| 374 | void | |||
| 375 | dc_eeprom_getword_xircom(struct dc_softc *sc, int addr, u_int16_t *dest) | |||
| 376 | { | |||
| 377 | SIO_SET(DC_SIO_ROMSEL | DC_SIO_ROMCTL_READ)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( (0x00001000 | 0x00004000))))); | |||
| 378 | ||||
| 379 | addr *= 2; | |||
| 380 | CSR_WRITE_4(sc, DC_ROM, addr | 0x160)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x50), (addr | 0x160))); | |||
| 381 | *dest = (u_int16_t)CSR_READ_4(sc, DC_SIO)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & 0xff; | |||
| 382 | addr += 1; | |||
| 383 | CSR_WRITE_4(sc, DC_ROM, addr | 0x160)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x50), (addr | 0x160))); | |||
| 384 | *dest |= ((u_int16_t)CSR_READ_4(sc, DC_SIO)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & 0xff) << 8; | |||
| 385 | ||||
| 386 | SIO_CLR(DC_SIO_ROMSEL | DC_SIO_ROMCTL_READ)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~((0x00001000 | 0x00004000))))); | |||
| 387 | } | |||
| 388 | ||||
| 389 | /* | |||
| 390 | * Read a word of data stored in the EEPROM at address 'addr.' | |||
| 391 | */ | |||
| 392 | void | |||
| 393 | dc_eeprom_getword(struct dc_softc *sc, int addr, u_int16_t *dest) | |||
| 394 | { | |||
| 395 | int i; | |||
| 396 | u_int16_t word = 0; | |||
| 397 | ||||
| 398 | /* Force EEPROM to idle state. */ | |||
| 399 | dc_eeprom_idle(sc); | |||
| 400 | ||||
| 401 | /* Enter EEPROM access mode. */ | |||
| 402 | CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (0x00000800 ))); | |||
| 403 | dc_delay(sc); | |||
| 404 | DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00004000)))); | |||
| 405 | dc_delay(sc); | |||
| 406 | DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00000002)))); | |||
| 407 | dc_delay(sc); | |||
| 408 | DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00000001)))); | |||
| 409 | dc_delay(sc); | |||
| 410 | ||||
| 411 | /* | |||
| 412 | * Send address of word we want to read. | |||
| 413 | */ | |||
| 414 | dc_eeprom_putbyte(sc, addr); | |||
| 415 | ||||
| 416 | /* | |||
| 417 | * Start reading bits from EEPROM. | |||
| 418 | */ | |||
| 419 | for (i = 0x8000; i; i >>= 1) { | |||
| 420 | SIO_SET(DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( (0x00000002))))); | |||
| 421 | dc_delay(sc); | |||
| 422 | if (CSR_READ_4(sc, DC_SIO)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & DC_SIO_EE_DATAOUT0x00000008) | |||
| 423 | word |= i; | |||
| 424 | dc_delay(sc); | |||
| 425 | SIO_CLR(DC_SIO_EE_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~((0x00000002))))); | |||
| 426 | dc_delay(sc); | |||
| 427 | } | |||
| 428 | ||||
| 429 | /* Turn off EEPROM access mode. */ | |||
| 430 | dc_eeprom_idle(sc); | |||
| 431 | ||||
| 432 | *dest = word; | |||
| 433 | } | |||
| 434 | ||||
| 435 | /* | |||
| 436 | * Read a sequence of words from the EEPROM. | |||
| 437 | */ | |||
| 438 | void | |||
| 439 | dc_read_eeprom(struct dc_softc *sc, caddr_t dest, int off, int cnt, | |||
| 440 | int swap) | |||
| 441 | { | |||
| 442 | int i; | |||
| 443 | u_int16_t word = 0, *ptr; | |||
| 444 | ||||
| 445 | for (i = 0; i < cnt; i++) { | |||
| 446 | if (DC_IS_PNIC(sc)(sc->dc_type == 0xA)) | |||
| 447 | dc_eeprom_getword_pnic(sc, off + i, &word); | |||
| 448 | else if (DC_IS_XIRCOM(sc)(sc->dc_type == 0xB)) | |||
| 449 | dc_eeprom_getword_xircom(sc, off + i, &word); | |||
| 450 | else | |||
| 451 | dc_eeprom_getword(sc, off + i, &word); | |||
| 452 | ptr = (u_int16_t *)(dest + (i * 2)); | |||
| 453 | if (swap) | |||
| 454 | *ptr = betoh16(word)(__uint16_t)(__builtin_constant_p(word) ? (__uint16_t)(((__uint16_t )(word) & 0xffU) << 8 | ((__uint16_t)(word) & 0xff00U ) >> 8) : __swap16md(word)); | |||
| 455 | else | |||
| 456 | *ptr = letoh16(word)((__uint16_t)(word)); | |||
| 457 | } | |||
| 458 | } | |||
| 459 | ||||
| 460 | /* | |||
| 461 | * The following two routines are taken from the Macronix 98713 | |||
| 462 | * Application Notes pp.19-21. | |||
| 463 | */ | |||
| 464 | /* | |||
| 465 | * Write a bit to the MII bus. | |||
| 466 | */ | |||
| 467 | void | |||
| 468 | dc_mii_writebit(struct dc_softc *sc, int bit) | |||
| 469 | { | |||
| 470 | if (bit) | |||
| 471 | CSR_WRITE_4(sc, DC_SIO,((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (0x00002000 |0x00020000))) | |||
| 472 | DC_SIO_ROMCTL_WRITE|DC_SIO_MII_DATAOUT)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (0x00002000 |0x00020000))); | |||
| 473 | else | |||
| 474 | CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (0x00002000 ))); | |||
| 475 | ||||
| 476 | DC_SETBIT(sc, DC_SIO, DC_SIO_MII_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00010000)))); | |||
| 477 | DC_CLRBIT(sc, DC_SIO, DC_SIO_MII_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00010000)))); | |||
| 478 | } | |||
| 479 | ||||
| 480 | /* | |||
| 481 | * Read a bit from the MII bus. | |||
| 482 | */ | |||
| 483 | int | |||
| 484 | dc_mii_readbit(struct dc_softc *sc) | |||
| 485 | { | |||
| 486 | CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_READ|DC_SIO_MII_DIR)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (0x00004000 |0x00040000))); | |||
| 487 | CSR_READ_4(sc, DC_SIO)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))); | |||
| 488 | DC_SETBIT(sc, DC_SIO, DC_SIO_MII_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) | ( 0x00010000)))); | |||
| 489 | DC_CLRBIT(sc, DC_SIO, DC_SIO_MII_CLK)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & ~(0x00010000)))); | |||
| 490 | if (CSR_READ_4(sc, DC_SIO)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x48))) & DC_SIO_MII_DATAIN0x00080000) | |||
| 491 | return (1); | |||
| 492 | return (0); | |||
| 493 | } | |||
| 494 | ||||
| 495 | /* | |||
| 496 | * Sync the PHYs by setting data bit and strobing the clock 32 times. | |||
| 497 | */ | |||
| 498 | void | |||
| 499 | dc_mii_sync(struct dc_softc *sc) | |||
| 500 | { | |||
| 501 | int i; | |||
| 502 | ||||
| 503 | CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x48), (0x00002000 ))); | |||
| 504 | ||||
| 505 | for (i = 0; i < 32; i++) | |||
| 506 | dc_mii_writebit(sc, 1); | |||
| 507 | } | |||
| 508 | ||||
| 509 | /* | |||
| 510 | * Clock a series of bits through the MII. | |||
| 511 | */ | |||
| 512 | void | |||
| 513 | dc_mii_send(struct dc_softc *sc, u_int32_t bits, int cnt) | |||
| 514 | { | |||
| 515 | int i; | |||
| 516 | ||||
| 517 | for (i = (0x1 << (cnt - 1)); i; i >>= 1) | |||
| 518 | dc_mii_writebit(sc, bits & i); | |||
| 519 | } | |||
| 520 | ||||
| 521 | /* | |||
| 522 | * Read an PHY register through the MII. | |||
| 523 | */ | |||
| 524 | int | |||
| 525 | dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame) | |||
| 526 | { | |||
| 527 | int i, ack, s; | |||
| 528 | ||||
| 529 | s = splnet()splraise(0x7); | |||
| 530 | ||||
| 531 | /* | |||
| 532 | * Set up frame for RX. | |||
| 533 | */ | |||
| 534 | frame->mii_stdelim = DC_MII_STARTDELIM0x01; | |||
| 535 | frame->mii_opcode = DC_MII_READOP0x02; | |||
| 536 | frame->mii_turnaround = 0; | |||
| 537 | frame->mii_data = 0; | |||
| 538 | ||||
| 539 | /* | |||
| 540 | * Sync the PHYs. | |||
| 541 | */ | |||
| 542 | dc_mii_sync(sc); | |||
| 543 | ||||
| 544 | /* | |||
| 545 | * Send command/address info. | |||
| 546 | */ | |||
| 547 | dc_mii_send(sc, frame->mii_stdelim, 2); | |||
| 548 | dc_mii_send(sc, frame->mii_opcode, 2); | |||
| 549 | dc_mii_send(sc, frame->mii_phyaddr, 5); | |||
| 550 | dc_mii_send(sc, frame->mii_regaddr, 5); | |||
| 551 | ||||
| 552 | #ifdef notdef | |||
| 553 | /* Idle bit */ | |||
| 554 | dc_mii_writebit(sc, 1); | |||
| 555 | dc_mii_writebit(sc, 0); | |||
| 556 | #endif | |||
| 557 | ||||
| 558 | /* Check for ack */ | |||
| 559 | ack = dc_mii_readbit(sc); | |||
| 560 | ||||
| 561 | /* | |||
| 562 | * Now try reading data bits. If the ack failed, we still | |||
| 563 | * need to clock through 16 cycles to keep the PHY(s) in sync. | |||
| 564 | */ | |||
| 565 | if (ack) { | |||
| 566 | for(i = 0; i < 16; i++) { | |||
| 567 | dc_mii_readbit(sc); | |||
| 568 | } | |||
| 569 | goto fail; | |||
| 570 | } | |||
| 571 | ||||
| 572 | for (i = 0x8000; i; i >>= 1) { | |||
| 573 | if (!ack) { | |||
| 574 | if (dc_mii_readbit(sc)) | |||
| 575 | frame->mii_data |= i; | |||
| 576 | } | |||
| 577 | } | |||
| 578 | ||||
| 579 | fail: | |||
| 580 | ||||
| 581 | dc_mii_writebit(sc, 0); | |||
| 582 | dc_mii_writebit(sc, 0); | |||
| 583 | ||||
| 584 | splx(s)spllower(s); | |||
| 585 | ||||
| 586 | if (ack) | |||
| 587 | return (1); | |||
| 588 | return (0); | |||
| 589 | } | |||
| 590 | ||||
| 591 | /* | |||
| 592 | * Write to a PHY register through the MII. | |||
| 593 | */ | |||
| 594 | int | |||
| 595 | dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame) | |||
| 596 | { | |||
| 597 | int s; | |||
| 598 | ||||
| 599 | s = splnet()splraise(0x7); | |||
| 600 | /* | |||
| 601 | * Set up frame for TX. | |||
| 602 | */ | |||
| 603 | ||||
| 604 | frame->mii_stdelim = DC_MII_STARTDELIM0x01; | |||
| 605 | frame->mii_opcode = DC_MII_WRITEOP0x01; | |||
| 606 | frame->mii_turnaround = DC_MII_TURNAROUND0x02; | |||
| 607 | ||||
| 608 | /* | |||
| 609 | * Sync the PHYs. | |||
| 610 | */ | |||
| 611 | dc_mii_sync(sc); | |||
| 612 | ||||
| 613 | dc_mii_send(sc, frame->mii_stdelim, 2); | |||
| 614 | dc_mii_send(sc, frame->mii_opcode, 2); | |||
| 615 | dc_mii_send(sc, frame->mii_phyaddr, 5); | |||
| 616 | dc_mii_send(sc, frame->mii_regaddr, 5); | |||
| 617 | dc_mii_send(sc, frame->mii_turnaround, 2); | |||
| 618 | dc_mii_send(sc, frame->mii_data, 16); | |||
| 619 | ||||
| 620 | /* Idle bit. */ | |||
| 621 | dc_mii_writebit(sc, 0); | |||
| 622 | dc_mii_writebit(sc, 0); | |||
| 623 | ||||
| 624 | splx(s)spllower(s); | |||
| 625 | return (0); | |||
| 626 | } | |||
| 627 | ||||
| 628 | int | |||
| 629 | dc_miibus_readreg(struct device *self, int phy, int reg) | |||
| 630 | { | |||
| 631 | struct dc_mii_frame frame; | |||
| 632 | struct dc_softc *sc = (struct dc_softc *)self; | |||
| 633 | int i, rval, phy_reg; | |||
| ||||
| 634 | ||||
| 635 | /* | |||
| 636 | * Note: both the AL981 and AN983 have internal PHYs, | |||
| 637 | * however the AL981 provides direct access to the PHY | |||
| 638 | * registers while the AN983 uses a serial MII interface. | |||
| 639 | * The AN983's MII interface is also buggy in that you | |||
| 640 | * can read from any MII address (0 to 31), but only address 1 | |||
| 641 | * behaves normally. To deal with both cases, we pretend | |||
| 642 | * that the PHY is at MII address 1. | |||
| 643 | */ | |||
| 644 | if (DC_IS_ADMTEK(sc)(sc->dc_type == 0x6 || sc->dc_type == 0x7) && phy != DC_ADMTEK_PHYADDR0x1) | |||
| 645 | return (0); | |||
| 646 | ||||
| 647 | /* | |||
| 648 | * Note: the ukphy probs of the RS7112 report a PHY at | |||
| 649 | * MII address 0 (possibly HomePNA?) and 1 (ethernet) | |||
| 650 | * so we only respond to correct one. | |||
| 651 | */ | |||
| 652 | if (DC_IS_CONEXANT(sc)(sc->dc_type == 0xC) && phy != DC_CONEXANT_PHYADDR0x1) | |||
| 653 | return (0); | |||
| 654 | ||||
| 655 | if (sc->dc_pmode != DC_PMODE_MII0x1) { | |||
| 656 | if (phy == (MII_NPHY32 - 1)) { | |||
| 657 | switch(reg) { | |||
| 658 | case MII_BMSR0x01: | |||
| 659 | /* | |||
| 660 | * Fake something to make the probe | |||
| 661 | * code think there's a PHY here. | |||
| 662 | */ | |||
| 663 | return (BMSR_MEDIAMASK(0x8000|0x4000|0x2000| 0x1000|0x0800|0x0400|0x0200)); | |||
| 664 | break; | |||
| 665 | case MII_PHYIDR10x02: | |||
| 666 | if (DC_IS_PNIC(sc)(sc->dc_type == 0xA)) | |||
| 667 | return (PCI_VENDOR_LITEON0x11ad); | |||
| 668 | return (PCI_VENDOR_DEC0x1011); | |||
| 669 | break; | |||
| 670 | case MII_PHYIDR20x03: | |||
| 671 | if (DC_IS_PNIC(sc)(sc->dc_type == 0xA)) | |||
| 672 | return (PCI_PRODUCT_LITEON_PNIC0x0002); | |||
| 673 | return (PCI_PRODUCT_DEC_211420x0019); | |||
| 674 | break; | |||
| 675 | default: | |||
| 676 | return (0); | |||
| 677 | break; | |||
| 678 | } | |||
| 679 | } else | |||
| 680 | return (0); | |||
| 681 | } | |||
| 682 | ||||
| 683 | if (DC_IS_PNIC(sc)(sc->dc_type == 0xA)) { | |||
| 684 | CSR_WRITE_4(sc, DC_PN_MII, DC_PN_MIIOPCODE_READ |((sc->dc_btag)->write_4((sc->dc_bhandle), (0xA0), (0x60020000 | (phy << 23) | (reg << 18)))) | |||
| 685 | (phy << 23) | (reg << 18))((sc->dc_btag)->write_4((sc->dc_bhandle), (0xA0), (0x60020000 | (phy << 23) | (reg << 18)))); | |||
| 686 | for (i = 0; i < DC_TIMEOUT1000; i++) { | |||
| 687 | DELAY(1)(*delay_func)(1); | |||
| 688 | rval = CSR_READ_4(sc, DC_PN_MII)((sc->dc_btag)->read_4((sc->dc_bhandle), (0xA0))); | |||
| 689 | if (!(rval & DC_PN_MII_BUSY0x80000000)) { | |||
| 690 | rval &= 0xFFFF; | |||
| 691 | return (rval == 0xFFFF ? 0 : rval); | |||
| 692 | } | |||
| 693 | } | |||
| 694 | return (0); | |||
| 695 | } | |||
| 696 | ||||
| 697 | if (DC_IS_COMET(sc)(sc->dc_type == 0x6)) { | |||
| 698 | switch(reg) { | |||
| 699 | case MII_BMCR0x00: | |||
| 700 | phy_reg = DC_AL_BMCR0xB4; | |||
| 701 | break; | |||
| 702 | case MII_BMSR0x01: | |||
| 703 | phy_reg = DC_AL_BMSR0xB8; | |||
| 704 | break; | |||
| 705 | case MII_PHYIDR10x02: | |||
| 706 | phy_reg = DC_AL_VENID0xBC; | |||
| 707 | break; | |||
| 708 | case MII_PHYIDR20x03: | |||
| 709 | phy_reg = DC_AL_DEVID0xC0; | |||
| 710 | break; | |||
| 711 | case MII_ANAR0x04: | |||
| 712 | phy_reg = DC_AL_ANAR0xC4; | |||
| 713 | break; | |||
| 714 | case MII_ANLPAR0x05: | |||
| 715 | phy_reg = DC_AL_LPAR0xC8; | |||
| 716 | break; | |||
| 717 | case MII_ANER0x06: | |||
| 718 | phy_reg = DC_AL_ANER0xCC; | |||
| 719 | break; | |||
| 720 | default: | |||
| 721 | printf("%s: phy_read: bad phy register %x\n", | |||
| 722 | sc->sc_dev.dv_xname, reg); | |||
| 723 | return (0); | |||
| 724 | break; | |||
| 725 | } | |||
| 726 | ||||
| 727 | rval = CSR_READ_4(sc, phy_reg)((sc->dc_btag)->read_4((sc->dc_bhandle), (phy_reg))) & 0x0000FFFF; | |||
| 728 | ||||
| 729 | if (rval == 0xFFFF) | |||
| 730 | return (0); | |||
| 731 | return (rval); | |||
| 732 | } | |||
| 733 | ||||
| 734 | bzero(&frame, sizeof(frame))__builtin_bzero((&frame), (sizeof(frame))); | |||
| 735 | ||||
| 736 | frame.mii_phyaddr = phy; | |||
| 737 | frame.mii_regaddr = reg; | |||
| 738 | if (sc->dc_type == DC_TYPE_987130x1) { | |||
| 739 | phy_reg = CSR_READ_4(sc, DC_NETCFG)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))); | |||
| 740 | CSR_WRITE_4(sc, DC_NETCFG, phy_reg & ~DC_NETCFG_PORTSEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (phy_reg & ~0x00040000))); | |||
| 741 | } | |||
| 742 | dc_mii_readreg(sc, &frame); | |||
| 743 | if (sc->dc_type == DC_TYPE_987130x1) | |||
| 744 | CSR_WRITE_4(sc, DC_NETCFG, phy_reg)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (phy_reg ))); | |||
| ||||
| 745 | ||||
| 746 | return (frame.mii_data); | |||
| 747 | } | |||
| 748 | ||||
| 749 | void | |||
| 750 | dc_miibus_writereg(struct device *self, int phy, int reg, int data) | |||
| 751 | { | |||
| 752 | struct dc_softc *sc = (struct dc_softc *)self; | |||
| 753 | struct dc_mii_frame frame; | |||
| 754 | int i, phy_reg; | |||
| 755 | ||||
| 756 | bzero(&frame, sizeof(frame))__builtin_bzero((&frame), (sizeof(frame))); | |||
| 757 | ||||
| 758 | if (DC_IS_ADMTEK(sc)(sc->dc_type == 0x6 || sc->dc_type == 0x7) && phy != DC_ADMTEK_PHYADDR0x1) | |||
| 759 | return; | |||
| 760 | if (DC_IS_CONEXANT(sc)(sc->dc_type == 0xC) && phy != DC_CONEXANT_PHYADDR0x1) | |||
| 761 | return; | |||
| 762 | ||||
| 763 | if (DC_IS_PNIC(sc)(sc->dc_type == 0xA)) { | |||
| 764 | CSR_WRITE_4(sc, DC_PN_MII, DC_PN_MIIOPCODE_WRITE |((sc->dc_btag)->write_4((sc->dc_bhandle), (0xA0), (0x50020000 | (phy << 23) | (reg << 10) | data))) | |||
| 765 | (phy << 23) | (reg << 10) | data)((sc->dc_btag)->write_4((sc->dc_bhandle), (0xA0), (0x50020000 | (phy << 23) | (reg << 10) | data))); | |||
| 766 | for (i = 0; i < DC_TIMEOUT1000; i++) { | |||
| 767 | if (!(CSR_READ_4(sc, DC_PN_MII)((sc->dc_btag)->read_4((sc->dc_bhandle), (0xA0))) & DC_PN_MII_BUSY0x80000000)) | |||
| 768 | break; | |||
| 769 | } | |||
| 770 | return; | |||
| 771 | } | |||
| 772 | ||||
| 773 | if (DC_IS_COMET(sc)(sc->dc_type == 0x6)) { | |||
| 774 | switch(reg) { | |||
| 775 | case MII_BMCR0x00: | |||
| 776 | phy_reg = DC_AL_BMCR0xB4; | |||
| 777 | break; | |||
| 778 | case MII_BMSR0x01: | |||
| 779 | phy_reg = DC_AL_BMSR0xB8; | |||
| 780 | break; | |||
| 781 | case MII_PHYIDR10x02: | |||
| 782 | phy_reg = DC_AL_VENID0xBC; | |||
| 783 | break; | |||
| 784 | case MII_PHYIDR20x03: | |||
| 785 | phy_reg = DC_AL_DEVID0xC0; | |||
| 786 | break; | |||
| 787 | case MII_ANAR0x04: | |||
| 788 | phy_reg = DC_AL_ANAR0xC4; | |||
| 789 | break; | |||
| 790 | case MII_ANLPAR0x05: | |||
| 791 | phy_reg = DC_AL_LPAR0xC8; | |||
| 792 | break; | |||
| 793 | case MII_ANER0x06: | |||
| 794 | phy_reg = DC_AL_ANER0xCC; | |||
| 795 | break; | |||
| 796 | default: | |||
| 797 | printf("%s: phy_write: bad phy register %x\n", | |||
| 798 | sc->sc_dev.dv_xname, reg); | |||
| 799 | return; | |||
| 800 | } | |||
| 801 | ||||
| 802 | CSR_WRITE_4(sc, phy_reg, data)((sc->dc_btag)->write_4((sc->dc_bhandle), (phy_reg), (data))); | |||
| 803 | return; | |||
| 804 | } | |||
| 805 | ||||
| 806 | frame.mii_phyaddr = phy; | |||
| 807 | frame.mii_regaddr = reg; | |||
| 808 | frame.mii_data = data; | |||
| 809 | ||||
| 810 | if (sc->dc_type == DC_TYPE_987130x1) { | |||
| 811 | phy_reg = CSR_READ_4(sc, DC_NETCFG)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))); | |||
| 812 | CSR_WRITE_4(sc, DC_NETCFG, phy_reg & ~DC_NETCFG_PORTSEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (phy_reg & ~0x00040000))); | |||
| 813 | } | |||
| 814 | dc_mii_writereg(sc, &frame); | |||
| 815 | if (sc->dc_type == DC_TYPE_987130x1) | |||
| 816 | CSR_WRITE_4(sc, DC_NETCFG, phy_reg)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (phy_reg ))); | |||
| 817 | } | |||
| 818 | ||||
| 819 | void | |||
| 820 | dc_miibus_statchg(struct device *self) | |||
| 821 | { | |||
| 822 | struct dc_softc *sc = (struct dc_softc *)self; | |||
| 823 | struct mii_data *mii; | |||
| 824 | struct ifmedia *ifm; | |||
| 825 | ||||
| 826 | if (DC_IS_ADMTEK(sc)(sc->dc_type == 0x6 || sc->dc_type == 0x7)) | |||
| 827 | return; | |||
| 828 | ||||
| 829 | mii = &sc->sc_mii; | |||
| 830 | ifm = &mii->mii_media; | |||
| 831 | if (DC_IS_DAVICOM(sc)(sc->dc_type == 0x8) && IFM_SUBTYPE(ifm->ifm_media)((ifm->ifm_media) & 0x00000000000000ffULL) == IFM_HPNA_117) { | |||
| 832 | dc_setcfg(sc, ifm->ifm_media); | |||
| 833 | sc->dc_if_media = ifm->ifm_media; | |||
| 834 | } else { | |||
| 835 | dc_setcfg(sc, mii->mii_media_active); | |||
| 836 | sc->dc_if_media = mii->mii_media_active; | |||
| 837 | } | |||
| 838 | } | |||
| 839 | ||||
| 840 | #define DC_BITS_5129 9 | |||
| 841 | #define DC_BITS_1287 7 | |||
| 842 | #define DC_BITS_646 6 | |||
| 843 | ||||
| 844 | u_int32_t | |||
| 845 | dc_crc_le(struct dc_softc *sc, caddr_t addr) | |||
| 846 | { | |||
| 847 | u_int32_t crc; | |||
| 848 | ||||
| 849 | /* Compute CRC for the address value. */ | |||
| 850 | crc = ether_crc32_le(addr, ETHER_ADDR_LEN6); | |||
| 851 | ||||
| 852 | /* | |||
| 853 | * The hash table on the PNIC II and the MX98715AEC-C/D/E | |||
| 854 | * chips is only 128 bits wide. | |||
| 855 | */ | |||
| 856 | if (sc->dc_flags & DC_128BIT_HASH0x00001000) | |||
| 857 | return (crc & ((1 << DC_BITS_1287) - 1)); | |||
| 858 | ||||
| 859 | /* The hash table on the MX98715BEC is only 64 bits wide. */ | |||
| 860 | if (sc->dc_flags & DC_64BIT_HASH0x00002000) | |||
| 861 | return (crc & ((1 << DC_BITS_646) - 1)); | |||
| 862 | ||||
| 863 | /* Xircom's hash filtering table is different (read: weird) */ | |||
| 864 | /* Xircom uses the LEAST significant bits */ | |||
| 865 | if (DC_IS_XIRCOM(sc)(sc->dc_type == 0xB)) { | |||
| 866 | if ((crc & 0x180) == 0x180) | |||
| 867 | return (crc & 0x0F) + (crc & 0x70)*3 + (14 << 4); | |||
| 868 | else | |||
| 869 | return (crc & 0x1F) + ((crc>>1) & 0xF0)*3 + (12 << 4); | |||
| 870 | } | |||
| 871 | ||||
| 872 | return (crc & ((1 << DC_BITS_5129) - 1)); | |||
| 873 | } | |||
| 874 | ||||
| 875 | /* | |||
| 876 | * Calculate CRC of a multicast group address, return the lower 6 bits. | |||
| 877 | */ | |||
| 878 | #define dc_crc_be(addr)((ether_crc32_be(addr,6) >> 26) & 0x0000003F) ((ether_crc32_be(addr,ETHER_ADDR_LEN6) >> 26) \ | |||
| 879 | & 0x0000003F) | |||
| 880 | ||||
| 881 | /* | |||
| 882 | * 21143-style RX filter setup routine. Filter programming is done by | |||
| 883 | * downloading a special setup frame into the TX engine. 21143, Macronix, | |||
| 884 | * PNIC, PNIC II and Davicom chips are programmed this way. | |||
| 885 | * | |||
| 886 | * We always program the chip using 'hash perfect' mode, i.e. one perfect | |||
| 887 | * address (our node address) and a 512-bit hash filter for multicast | |||
| 888 | * frames. We also sneak the broadcast address into the hash filter since | |||
| 889 | * we need that too. | |||
| 890 | */ | |||
| 891 | void | |||
| 892 | dc_setfilt_21143(struct dc_softc *sc) | |||
| 893 | { | |||
| 894 | struct arpcom *ac = &sc->sc_arpcom; | |||
| 895 | struct ifnet *ifp = &sc->sc_arpcom.ac_if; | |||
| 896 | struct ether_multi *enm; | |||
| 897 | struct ether_multistep step; | |||
| 898 | struct dc_desc *sframe; | |||
| 899 | u_int32_t h, *sp; | |||
| 900 | int i; | |||
| 901 | ||||
| 902 | i = sc->dc_cdata.dc_tx_prod; | |||
| 903 | DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT)(sc->dc_cdata.dc_tx_prod) = (sc->dc_cdata.dc_tx_prod + 1 ) % 256; | |||
| 904 | sc->dc_cdata.dc_tx_cnt++; | |||
| 905 | sframe = &sc->dc_ldata->dc_tx_list[i]; | |||
| 906 | sp = &sc->dc_ldata->dc_sbuf[0]; | |||
| 907 | bzero(sp, DC_SFRAME_LEN)__builtin_bzero((sp), (192)); | |||
| 908 | ||||
| 909 | sframe->dc_datadc_ptr1 = htole32(sc->sc_listmap->dm_segs[0].ds_addr +((__uint32_t)(sc->sc_listmap->dm_segs[0].ds_addr + __builtin_offsetof (struct dc_list_data, dc_sbuf))) | |||
| 910 | offsetof(struct dc_list_data, dc_sbuf))((__uint32_t)(sc->sc_listmap->dm_segs[0].ds_addr + __builtin_offsetof (struct dc_list_data, dc_sbuf))); | |||
| 911 | sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP |((__uint32_t)(192 | 0x08000000 | 0x01000000 | 0x00400000 | 0x80000000 )) | |||
| 912 | DC_TXCTL_TLINK | DC_FILTER_HASHPERF | DC_TXCTL_FINT)((__uint32_t)(192 | 0x08000000 | 0x01000000 | 0x00400000 | 0x80000000 )); | |||
| 913 | ||||
| 914 | sc->dc_cdata.dc_tx_chain[i].sd_mbuf = | |||
| 915 | (struct mbuf *)&sc->dc_ldata->dc_sbuf[0]; | |||
| 916 | ||||
| 917 | DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ALLMULTI | DC_NETCFG_RX_PROMISC))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~((0x00000080 | 0x00000040))))); | |||
| 918 | ifp->if_flags &= ~IFF_ALLMULTI0x200; | |||
| 919 | ||||
| 920 | if (ifp->if_flags & IFF_PROMISC0x100 || ac->ac_multirangecnt > 0) { | |||
| 921 | ifp->if_flags |= IFF_ALLMULTI0x200; | |||
| 922 | if (ifp->if_flags & IFF_PROMISC0x100) | |||
| 923 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00000040)))); | |||
| 924 | else | |||
| 925 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00000080)))); | |||
| 926 | } else { | |||
| 927 | ETHER_FIRST_MULTI(step, ac, enm)do { (step).e_enm = ((&(ac)->ac_multiaddrs)->lh_first ); do { if ((((enm)) = ((step)).e_enm) != ((void *)0)) ((step )).e_enm = ((((enm)))->enm_list.le_next); } while ( 0); } while ( 0); | |||
| 928 | while (enm != NULL((void *)0)) { | |||
| 929 | h = dc_crc_le(sc, enm->enm_addrlo); | |||
| 930 | ||||
| 931 | sp[h >> 4] |= htole32(1 << (h & 0xF))((__uint32_t)(1 << (h & 0xF))); | |||
| 932 | ||||
| 933 | ETHER_NEXT_MULTI(step, enm)do { if (((enm) = (step).e_enm) != ((void *)0)) (step).e_enm = (((enm))->enm_list.le_next); } while ( 0); | |||
| 934 | } | |||
| 935 | } | |||
| 936 | ||||
| 937 | /* | |||
| 938 | * Always accept broadcast frames. | |||
| 939 | */ | |||
| 940 | h = dc_crc_le(sc, (caddr_t)ðerbroadcastaddr); | |||
| 941 | sp[h >> 4] |= htole32(1 << (h & 0xF))((__uint32_t)(1 << (h & 0xF))); | |||
| 942 | ||||
| 943 | /* Set our MAC address */ | |||
| 944 | sp[39] = DC_SP_FIELD(sc->sc_arpcom.ac_enaddr, 0)(((u_int16_t *)(sc->sc_arpcom.ac_enaddr))[(0)]); | |||
| 945 | sp[40] = DC_SP_FIELD(sc->sc_arpcom.ac_enaddr, 1)(((u_int16_t *)(sc->sc_arpcom.ac_enaddr))[(1)]); | |||
| 946 | sp[41] = DC_SP_FIELD(sc->sc_arpcom.ac_enaddr, 2)(((u_int16_t *)(sc->sc_arpcom.ac_enaddr))[(2)]); | |||
| 947 | ||||
| 948 | bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_sbuf [0])), (sizeof(struct dc_list_data) - __builtin_offsetof(struct dc_list_data, dc_sbuf[0])), (0x01 | 0x04)) | |||
| 949 | offsetof(struct dc_list_data, dc_sbuf[0]),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_sbuf [0])), (sizeof(struct dc_list_data) - __builtin_offsetof(struct dc_list_data, dc_sbuf[0])), (0x01 | 0x04)) | |||
| 950 | sizeof(struct dc_list_data) -(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_sbuf [0])), (sizeof(struct dc_list_data) - __builtin_offsetof(struct dc_list_data, dc_sbuf[0])), (0x01 | 0x04)) | |||
| 951 | offsetof(struct dc_list_data, dc_sbuf[0]),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_sbuf [0])), (sizeof(struct dc_list_data) - __builtin_offsetof(struct dc_list_data, dc_sbuf[0])), (0x01 | 0x04)) | |||
| 952 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_sbuf [0])), (sizeof(struct dc_list_data) - __builtin_offsetof(struct dc_list_data, dc_sbuf[0])), (0x01 | 0x04)); | |||
| 953 | ||||
| 954 | sframe->dc_status = htole32(DC_TXSTAT_OWN)((__uint32_t)(0x80000000)); | |||
| 955 | ||||
| 956 | bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_tx_list [i])), (sizeof(struct dc_desc)), (0x01 | 0x04)) | |||
| 957 | offsetof(struct dc_list_data, dc_tx_list[i]),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_tx_list [i])), (sizeof(struct dc_desc)), (0x01 | 0x04)) | |||
| 958 | sizeof(struct dc_desc), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_tx_list [i])), (sizeof(struct dc_desc)), (0x01 | 0x04)); | |||
| 959 | ||||
| 960 | CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x08), (0xFFFFFFFF ))); | |||
| 961 | ||||
| 962 | /* | |||
| 963 | * The PNIC takes an exceedingly long time to process its | |||
| 964 | * setup frame; wait 10ms after posting the setup frame | |||
| 965 | * before proceeding, just so it has time to swallow its | |||
| 966 | * medicine. | |||
| 967 | */ | |||
| 968 | DELAY(10000)(*delay_func)(10000); | |||
| 969 | ||||
| 970 | ifp->if_timer = 5; | |||
| 971 | } | |||
| 972 | ||||
| 973 | void | |||
| 974 | dc_setfilt_admtek(struct dc_softc *sc) | |||
| 975 | { | |||
| 976 | struct arpcom *ac = &sc->sc_arpcom; | |||
| 977 | struct ifnet *ifp = &sc->sc_arpcom.ac_if; | |||
| 978 | struct ether_multi *enm; | |||
| 979 | struct ether_multistep step; | |||
| 980 | u_int32_t hashes[2]; | |||
| 981 | int h = 0; | |||
| 982 | ||||
| 983 | DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ALLMULTI | DC_NETCFG_RX_PROMISC))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~((0x00000080 | 0x00000040))))); | |||
| 984 | bzero(hashes, sizeof(hashes))__builtin_bzero((hashes), (sizeof(hashes))); | |||
| 985 | ifp->if_flags &= ~IFF_ALLMULTI0x200; | |||
| 986 | ||||
| 987 | if (ifp->if_flags & IFF_PROMISC0x100 || ac->ac_multirangecnt > 0) { | |||
| 988 | ifp->if_flags |= IFF_ALLMULTI0x200; | |||
| 989 | if (ifp->if_flags & IFF_PROMISC0x100) | |||
| 990 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00000040)))); | |||
| 991 | else | |||
| 992 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00000080)))); | |||
| 993 | } else { | |||
| 994 | /* now program new ones */ | |||
| 995 | ETHER_FIRST_MULTI(step, ac, enm)do { (step).e_enm = ((&(ac)->ac_multiaddrs)->lh_first ); do { if ((((enm)) = ((step)).e_enm) != ((void *)0)) ((step )).e_enm = ((((enm)))->enm_list.le_next); } while ( 0); } while ( 0); | |||
| 996 | while (enm != NULL((void *)0)) { | |||
| 997 | if (DC_IS_CENTAUR(sc)(sc->dc_type == 0x7)) | |||
| 998 | h = dc_crc_le(sc, enm->enm_addrlo); | |||
| 999 | else | |||
| 1000 | h = dc_crc_be(enm->enm_addrlo)((ether_crc32_be(enm->enm_addrlo,6) >> 26) & 0x0000003F ); | |||
| 1001 | ||||
| 1002 | if (h < 32) | |||
| 1003 | hashes[0] |= (1 << h); | |||
| 1004 | else | |||
| 1005 | hashes[1] |= (1 << (h - 32)); | |||
| 1006 | ||||
| 1007 | ETHER_NEXT_MULTI(step, enm)do { if (((enm) = (step).e_enm) != ((void *)0)) (step).e_enm = (((enm))->enm_list.le_next); } while ( 0); | |||
| 1008 | } | |||
| 1009 | } | |||
| 1010 | ||||
| 1011 | /* Init our MAC address */ | |||
| 1012 | CSR_WRITE_4(sc, DC_AL_PAR0, ac->ac_enaddr[3] << 24 |((sc->dc_btag)->write_4((sc->dc_bhandle), (0xA4), (ac ->ac_enaddr[3] << 24 | ac->ac_enaddr[2] << 16 | ac->ac_enaddr[1] << 8 | ac->ac_enaddr[0]))) | |||
| 1013 | ac->ac_enaddr[2] << 16 | ac->ac_enaddr[1] << 8 | ac->ac_enaddr[0])((sc->dc_btag)->write_4((sc->dc_bhandle), (0xA4), (ac ->ac_enaddr[3] << 24 | ac->ac_enaddr[2] << 16 | ac->ac_enaddr[1] << 8 | ac->ac_enaddr[0]))); | |||
| 1014 | CSR_WRITE_4(sc, DC_AL_PAR1, ac->ac_enaddr[5] << 8 | ac->ac_enaddr[4])((sc->dc_btag)->write_4((sc->dc_bhandle), (0xA8), (ac ->ac_enaddr[5] << 8 | ac->ac_enaddr[4]))); | |||
| 1015 | ||||
| 1016 | CSR_WRITE_4(sc, DC_AL_MAR0, hashes[0])((sc->dc_btag)->write_4((sc->dc_bhandle), (0xAC), (hashes [0]))); | |||
| 1017 | CSR_WRITE_4(sc, DC_AL_MAR1, hashes[1])((sc->dc_btag)->write_4((sc->dc_bhandle), (0xB0), (hashes [1]))); | |||
| 1018 | } | |||
| 1019 | ||||
| 1020 | void | |||
| 1021 | dc_setfilt_asix(struct dc_softc *sc) | |||
| 1022 | { | |||
| 1023 | struct arpcom *ac = &sc->sc_arpcom; | |||
| 1024 | struct ifnet *ifp = &sc->sc_arpcom.ac_if; | |||
| 1025 | struct ether_multi *enm; | |||
| 1026 | struct ether_multistep step; | |||
| 1027 | u_int32_t hashes[2]; | |||
| 1028 | int h = 0; | |||
| 1029 | ||||
| 1030 | DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ALLMULTI | DC_AX_NETCFG_RX_BROAD |((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~((0x00000080 | 0x00000100 | 0x00000040))))) | |||
| 1031 | DC_NETCFG_RX_PROMISC))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~((0x00000080 | 0x00000100 | 0x00000040))))); | |||
| 1032 | bzero(hashes, sizeof(hashes))__builtin_bzero((hashes), (sizeof(hashes))); | |||
| 1033 | ifp->if_flags &= ~IFF_ALLMULTI0x200; | |||
| 1034 | ||||
| 1035 | /* | |||
| 1036 | * Always accept broadcast frames. | |||
| 1037 | */ | |||
| 1038 | DC_SETBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00000100)))); | |||
| 1039 | ||||
| 1040 | if (ifp->if_flags & IFF_PROMISC0x100 || ac->ac_multirangecnt > 0) { | |||
| 1041 | ifp->if_flags |= IFF_ALLMULTI0x200; | |||
| 1042 | if (ifp->if_flags & IFF_PROMISC0x100) | |||
| 1043 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00000040)))); | |||
| 1044 | else | |||
| 1045 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00000080)))); | |||
| 1046 | } else { | |||
| 1047 | /* now program new ones */ | |||
| 1048 | ETHER_FIRST_MULTI(step, ac, enm)do { (step).e_enm = ((&(ac)->ac_multiaddrs)->lh_first ); do { if ((((enm)) = ((step)).e_enm) != ((void *)0)) ((step )).e_enm = ((((enm)))->enm_list.le_next); } while ( 0); } while ( 0); | |||
| 1049 | while (enm != NULL((void *)0)) { | |||
| 1050 | h = dc_crc_be(enm->enm_addrlo)((ether_crc32_be(enm->enm_addrlo,6) >> 26) & 0x0000003F ); | |||
| 1051 | ||||
| 1052 | if (h < 32) | |||
| 1053 | hashes[0] |= (1 << h); | |||
| 1054 | else | |||
| 1055 | hashes[1] |= (1 << (h - 32)); | |||
| 1056 | ||||
| 1057 | ETHER_NEXT_MULTI(step, enm)do { if (((enm) = (step).e_enm) != ((void *)0)) (step).e_enm = (((enm))->enm_list.le_next); } while ( 0); | |||
| 1058 | } | |||
| 1059 | } | |||
| 1060 | ||||
| 1061 | /* Init our MAC address */ | |||
| 1062 | CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR0)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x68), (0x00000000 ))); | |||
| 1063 | CSR_WRITE_4(sc, DC_AX_FILTDATA,((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (* (u_int32_t *)(&sc->sc_arpcom.ac_enaddr[0])))) | |||
| 1064 | *(u_int32_t *)(&sc->sc_arpcom.ac_enaddr[0]))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (* (u_int32_t *)(&sc->sc_arpcom.ac_enaddr[0])))); | |||
| 1065 | CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR1)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x68), (0x00000001 ))); | |||
| 1066 | CSR_WRITE_4(sc, DC_AX_FILTDATA,((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (* (u_int32_t *)(&sc->sc_arpcom.ac_enaddr[4])))) | |||
| 1067 | *(u_int32_t *)(&sc->sc_arpcom.ac_enaddr[4]))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (* (u_int32_t *)(&sc->sc_arpcom.ac_enaddr[4])))); | |||
| 1068 | ||||
| 1069 | CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x68), (0x00000002 ))); | |||
| 1070 | CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[0])((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (hashes [0]))); | |||
| 1071 | CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR1)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x68), (0x00000003 ))); | |||
| 1072 | CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[1])((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (hashes [1]))); | |||
| 1073 | } | |||
| 1074 | ||||
| 1075 | void | |||
| 1076 | dc_setfilt_xircom(struct dc_softc *sc) | |||
| 1077 | { | |||
| 1078 | struct arpcom *ac = &sc->sc_arpcom; | |||
| 1079 | struct ifnet *ifp = &sc->sc_arpcom.ac_if; | |||
| 1080 | struct ether_multi *enm; | |||
| 1081 | struct ether_multistep step; | |||
| 1082 | struct dc_desc *sframe; | |||
| 1083 | u_int32_t h, *sp; | |||
| 1084 | int i; | |||
| 1085 | ||||
| 1086 | DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON|DC_NETCFG_RX_ON))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~((0x00002000|0x00000002))))); | |||
| 1087 | ||||
| 1088 | i = sc->dc_cdata.dc_tx_prod; | |||
| 1089 | DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT)(sc->dc_cdata.dc_tx_prod) = (sc->dc_cdata.dc_tx_prod + 1 ) % 256; | |||
| 1090 | sc->dc_cdata.dc_tx_cnt++; | |||
| 1091 | sframe = &sc->dc_ldata->dc_tx_list[i]; | |||
| 1092 | sp = &sc->dc_ldata->dc_sbuf[0]; | |||
| 1093 | bzero(sp, DC_SFRAME_LEN)__builtin_bzero((sp), (192)); | |||
| 1094 | ||||
| 1095 | sframe->dc_datadc_ptr1 = htole32(sc->sc_listmap->dm_segs[0].ds_addr +((__uint32_t)(sc->sc_listmap->dm_segs[0].ds_addr + __builtin_offsetof (struct dc_list_data, dc_sbuf))) | |||
| 1096 | offsetof(struct dc_list_data, dc_sbuf))((__uint32_t)(sc->sc_listmap->dm_segs[0].ds_addr + __builtin_offsetof (struct dc_list_data, dc_sbuf))); | |||
| 1097 | sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP |((__uint32_t)(192 | 0x08000000 | 0x01000000 | 0x00400000 | 0x80000000 )) | |||
| 1098 | DC_TXCTL_TLINK | DC_FILTER_HASHPERF | DC_TXCTL_FINT)((__uint32_t)(192 | 0x08000000 | 0x01000000 | 0x00400000 | 0x80000000 )); | |||
| 1099 | ||||
| 1100 | sc->dc_cdata.dc_tx_chain[i].sd_mbuf = | |||
| 1101 | (struct mbuf *)&sc->dc_ldata->dc_sbuf[0]; | |||
| 1102 | ||||
| 1103 | DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ALLMULTI | DC_NETCFG_RX_PROMISC))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~((0x00000080 | 0x00000040))))); | |||
| 1104 | ifp->if_flags &= ~IFF_ALLMULTI0x200; | |||
| 1105 | ||||
| 1106 | if (ifp->if_flags & IFF_PROMISC0x100 || ac->ac_multirangecnt > 0) { | |||
| 1107 | ifp->if_flags |= IFF_ALLMULTI0x200; | |||
| 1108 | if (ifp->if_flags & IFF_PROMISC0x100) | |||
| 1109 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00000040)))); | |||
| 1110 | else | |||
| 1111 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00000080)))); | |||
| 1112 | } else { | |||
| 1113 | /* now program new ones */ | |||
| 1114 | ETHER_FIRST_MULTI(step, ac, enm)do { (step).e_enm = ((&(ac)->ac_multiaddrs)->lh_first ); do { if ((((enm)) = ((step)).e_enm) != ((void *)0)) ((step )).e_enm = ((((enm)))->enm_list.le_next); } while ( 0); } while ( 0); | |||
| 1115 | while (enm != NULL((void *)0)) { | |||
| 1116 | h = dc_crc_le(sc, enm->enm_addrlo); | |||
| 1117 | ||||
| 1118 | sp[h >> 4] |= htole32(1 << (h & 0xF))((__uint32_t)(1 << (h & 0xF))); | |||
| 1119 | ||||
| 1120 | ETHER_NEXT_MULTI(step, enm)do { if (((enm) = (step).e_enm) != ((void *)0)) (step).e_enm = (((enm))->enm_list.le_next); } while ( 0); | |||
| 1121 | } | |||
| 1122 | } | |||
| 1123 | ||||
| 1124 | /* | |||
| 1125 | * Always accept broadcast frames. | |||
| 1126 | */ | |||
| 1127 | h = dc_crc_le(sc, (caddr_t)ðerbroadcastaddr); | |||
| 1128 | sp[h >> 4] |= htole32(1 << (h & 0xF))((__uint32_t)(1 << (h & 0xF))); | |||
| 1129 | ||||
| 1130 | /* Set our MAC address */ | |||
| 1131 | sp[0] = DC_SP_FIELD(sc->sc_arpcom.ac_enaddr, 0)(((u_int16_t *)(sc->sc_arpcom.ac_enaddr))[(0)]); | |||
| 1132 | sp[1] = DC_SP_FIELD(sc->sc_arpcom.ac_enaddr, 1)(((u_int16_t *)(sc->sc_arpcom.ac_enaddr))[(1)]); | |||
| 1133 | sp[2] = DC_SP_FIELD(sc->sc_arpcom.ac_enaddr, 2)(((u_int16_t *)(sc->sc_arpcom.ac_enaddr))[(2)]); | |||
| 1134 | ||||
| 1135 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00002000)))); | |||
| 1136 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00000002)))); | |||
| 1137 | ifp->if_flags |= IFF_RUNNING0x40; | |||
| 1138 | sframe->dc_status = htole32(DC_TXSTAT_OWN)((__uint32_t)(0x80000000)); | |||
| 1139 | CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x08), (0xFFFFFFFF ))); | |||
| 1140 | ||||
| 1141 | /* | |||
| 1142 | * wait some time... | |||
| 1143 | */ | |||
| 1144 | DELAY(1000)(*delay_func)(1000); | |||
| 1145 | ||||
| 1146 | ifp->if_timer = 5; | |||
| 1147 | } | |||
| 1148 | ||||
| 1149 | void | |||
| 1150 | dc_setfilt(struct dc_softc *sc) | |||
| 1151 | { | |||
| 1152 | if (DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD) || DC_IS_MACRONIX(sc)(sc->dc_type == 0x1 || sc->dc_type == 0x2 || sc->dc_type == 0x3) || DC_IS_PNIC(sc)(sc->dc_type == 0xA) || | |||
| 1153 | DC_IS_PNICII(sc)(sc->dc_type == 0x9) || DC_IS_DAVICOM(sc)(sc->dc_type == 0x8) || DC_IS_CONEXANT(sc)(sc->dc_type == 0xC)) | |||
| 1154 | dc_setfilt_21143(sc); | |||
| 1155 | ||||
| 1156 | if (DC_IS_ASIX(sc)(sc->dc_type == 0x5)) | |||
| 1157 | dc_setfilt_asix(sc); | |||
| 1158 | ||||
| 1159 | if (DC_IS_ADMTEK(sc)(sc->dc_type == 0x6 || sc->dc_type == 0x7)) | |||
| 1160 | dc_setfilt_admtek(sc); | |||
| 1161 | ||||
| 1162 | if (DC_IS_XIRCOM(sc)(sc->dc_type == 0xB)) | |||
| 1163 | dc_setfilt_xircom(sc); | |||
| 1164 | } | |||
| 1165 | ||||
| 1166 | /* | |||
| 1167 | * In order to fiddle with the | |||
| 1168 | * 'full-duplex' and '100Mbps' bits in the netconfig register, we | |||
| 1169 | * first have to put the transmit and/or receive logic in the idle state. | |||
| 1170 | */ | |||
| 1171 | void | |||
| 1172 | dc_setcfg(struct dc_softc *sc, uint64_t media) | |||
| 1173 | { | |||
| 1174 | int i, restart = 0; | |||
| 1175 | u_int32_t isr; | |||
| 1176 | ||||
| 1177 | if (IFM_SUBTYPE(media)((media) & 0x00000000000000ffULL) == IFM_NONE2ULL) | |||
| 1178 | return; | |||
| 1179 | ||||
| 1180 | if (CSR_READ_4(sc, DC_NETCFG)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & (DC_NETCFG_TX_ON0x00002000|DC_NETCFG_RX_ON0x00000002)) { | |||
| 1181 | restart = 1; | |||
| 1182 | DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON|DC_NETCFG_RX_ON))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~((0x00002000|0x00000002))))); | |||
| 1183 | ||||
| 1184 | for (i = 0; i < DC_TIMEOUT1000; i++) { | |||
| 1185 | isr = CSR_READ_4(sc, DC_ISR)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x28))); | |||
| 1186 | if (isr & DC_ISR_TX_IDLE0x00000002 && | |||
| 1187 | ((isr & DC_ISR_RX_STATE0x000E0000) == DC_RXSTATE_STOPPED0x00000000 || | |||
| 1188 | (isr & DC_ISR_RX_STATE0x000E0000) == DC_RXSTATE_WAIT0x00060000)) | |||
| 1189 | break; | |||
| 1190 | DELAY(10)(*delay_func)(10); | |||
| 1191 | } | |||
| 1192 | ||||
| 1193 | if (i == DC_TIMEOUT1000) { | |||
| 1194 | if (!(isr & DC_ISR_TX_IDLE0x00000002) && !DC_IS_ASIX(sc)(sc->dc_type == 0x5)) | |||
| 1195 | printf("%s: failed to force tx to idle state\n", | |||
| 1196 | sc->sc_dev.dv_xname); | |||
| 1197 | if (!((isr & DC_ISR_RX_STATE0x000E0000) == DC_RXSTATE_STOPPED0x00000000 || | |||
| 1198 | (isr & DC_ISR_RX_STATE0x000E0000) == DC_RXSTATE_WAIT0x00060000) && | |||
| 1199 | !DC_HAS_BROKEN_RXSTATE(sc)((sc->dc_type == 0x7) || (sc->dc_type == 0xC) || ((sc-> dc_type == 0x8) && sc->dc_revision >= 0x30))) | |||
| 1200 | printf("%s: failed to force rx to idle state\n", | |||
| 1201 | sc->sc_dev.dv_xname); | |||
| 1202 | } | |||
| 1203 | } | |||
| 1204 | ||||
| 1205 | if (IFM_SUBTYPE(media)((media) & 0x00000000000000ffULL) == IFM_100_TX6) { | |||
| 1206 | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~(0x00400000)))); | |||
| 1207 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00080000)))); | |||
| 1208 | if (sc->dc_pmode == DC_PMODE_MII0x1) { | |||
| 1209 | int watchdogreg; | |||
| 1210 | ||||
| 1211 | if (DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD)) { | |||
| 1212 | /* there's a write enable bit here that reads as 1 */ | |||
| 1213 | watchdogreg = CSR_READ_4(sc, DC_WATCHDOG)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x78))); | |||
| 1214 | watchdogreg &= ~DC_WDOG_CTLWREN0x08000000; | |||
| 1215 | watchdogreg |= DC_WDOG_JABBERDIS0x00000001; | |||
| 1216 | CSR_WRITE_4(sc, DC_WATCHDOG, watchdogreg)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (watchdogreg ))); | |||
| 1217 | } else { | |||
| 1218 | DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x78))) | ( 0x00000001)))); | |||
| 1219 | } | |||
| 1220 | DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS|((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~((0x00800000| 0x00040000|0x01000000))))) | |||
| 1221 | DC_NETCFG_PORTSEL|DC_NETCFG_SCRAMBLER))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~((0x00800000| 0x00040000|0x01000000))))); | |||
| 1222 | if (sc->dc_type == DC_TYPE_987130x1) | |||
| 1223 | DC_SETBIT(sc, DC_NETCFG, (DC_NETCFG_PCS|((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( (0x00800000| 0x01000000))))) | |||
| 1224 | DC_NETCFG_SCRAMBLER))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( (0x00800000| 0x01000000))))); | |||
| 1225 | if (!DC_IS_DAVICOM(sc)(sc->dc_type == 0x8)) | |||
| 1226 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00040000)))); | |||
| 1227 | DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x70))) & ~(0xFFFF)))); | |||
| 1228 | if (DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD)) | |||
| 1229 | dc_apply_fixup(sc, IFM_AUTO0ULL); | |||
| 1230 | } else { | |||
| 1231 | if (DC_IS_PNIC(sc)(sc->dc_type == 0xA)) { | |||
| 1232 | DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_SPEEDSEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x60), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x60))) | ( ((0x000000001) | (0x000000001 << 4)))))); | |||
| 1233 | DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_100TX_LOOP)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x60), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x60))) | ( ((0x000000002) | (0x000000002 << 4)))))); | |||
| 1234 | DC_SETBIT(sc, DC_PN_NWAY, DC_PN_NWAY_SPEEDSEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0xB8), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0xB8))) | ( 0x00000800)))); | |||
| 1235 | } | |||
| 1236 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00040000)))); | |||
| 1237 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00800000)))); | |||
| 1238 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x01000000)))); | |||
| 1239 | if (DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD)) | |||
| 1240 | dc_apply_fixup(sc, | |||
| 1241 | (media & IFM_GMASK0x00ffff0000000000ULL) == IFM_FDX0x0000010000000000ULL ? | |||
| 1242 | IFM_100_TX6|IFM_FDX0x0000010000000000ULL : IFM_100_TX6); | |||
| 1243 | } | |||
| 1244 | } | |||
| 1245 | ||||
| 1246 | if (IFM_SUBTYPE(media)((media) & 0x00000000000000ffULL) == IFM_10_T3) { | |||
| 1247 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00400000)))); | |||
| 1248 | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~(0x00080000)))); | |||
| 1249 | if (sc->dc_pmode == DC_PMODE_MII0x1) { | |||
| 1250 | int watchdogreg; | |||
| 1251 | ||||
| 1252 | if (DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD)) { | |||
| 1253 | /* there's a write enable bit here that reads as 1 */ | |||
| 1254 | watchdogreg = CSR_READ_4(sc, DC_WATCHDOG)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x78))); | |||
| 1255 | watchdogreg &= ~DC_WDOG_CTLWREN0x08000000; | |||
| 1256 | watchdogreg |= DC_WDOG_JABBERDIS0x00000001; | |||
| 1257 | CSR_WRITE_4(sc, DC_WATCHDOG, watchdogreg)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (watchdogreg ))); | |||
| 1258 | } else { | |||
| 1259 | DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x78))) | ( 0x00000001)))); | |||
| 1260 | } | |||
| 1261 | DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS|((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~((0x00800000| 0x00040000|0x01000000))))) | |||
| 1262 | DC_NETCFG_PORTSEL|DC_NETCFG_SCRAMBLER))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~((0x00800000| 0x00040000|0x01000000))))); | |||
| 1263 | if (sc->dc_type == DC_TYPE_987130x1) | |||
| 1264 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00800000)))); | |||
| 1265 | if (!DC_IS_DAVICOM(sc)(sc->dc_type == 0x8)) | |||
| 1266 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00040000)))); | |||
| 1267 | DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x70))) & ~(0xFFFF)))); | |||
| 1268 | if (DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD)) | |||
| 1269 | dc_apply_fixup(sc, IFM_AUTO0ULL); | |||
| 1270 | } else { | |||
| 1271 | if (DC_IS_PNIC(sc)(sc->dc_type == 0xA)) { | |||
| 1272 | DC_PN_GPIO_CLRBIT(sc, DC_PN_GPIO_SPEEDSEL){ ((sc->dc_btag)->write_4((sc->dc_bhandle), (0x60), ( ((sc->dc_btag)->read_4((sc->dc_bhandle), (0x60))) | ( ((0x000000001) << 4))))); ((sc->dc_btag)->write_4 ((sc->dc_bhandle), (0x60), (((sc->dc_btag)->read_4(( sc->dc_bhandle), (0x60))) & ~((0x000000001))))); }; | |||
| 1273 | DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_100TX_LOOP)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x60), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x60))) | ( ((0x000000002) | (0x000000002 << 4)))))); | |||
| 1274 | DC_CLRBIT(sc, DC_PN_NWAY, DC_PN_NWAY_SPEEDSEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0xB8), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0xB8))) & ~(0x00000800)))); | |||
| 1275 | } | |||
| 1276 | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~(0x00040000)))); | |||
| 1277 | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PCS)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~(0x00800000)))); | |||
| 1278 | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~(0x01000000)))); | |||
| 1279 | if (DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD)) { | |||
| 1280 | DC_CLRBIT(sc, DC_SIARESET, DC_SIA_RESET)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x68), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x68))) & ~(0x00000001)))); | |||
| 1281 | DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x70))) & ~(0xFFFF)))); | |||
| 1282 | if ((media & IFM_GMASK0x00ffff0000000000ULL) == IFM_FDX0x0000010000000000ULL) | |||
| 1283 | DC_SETBIT(sc, DC_10BTCTRL, 0x7F3D)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x70))) | ( 0x7F3D)))); | |||
| 1284 | else | |||
| 1285 | DC_SETBIT(sc, DC_10BTCTRL, 0x7F3F)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x70))) | ( 0x7F3F)))); | |||
| 1286 | DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x68), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x68))) | ( 0x00000001)))); | |||
| 1287 | DC_CLRBIT(sc, DC_10BTCTRL,((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x70))) & ~(0x00000080)))) | |||
| 1288 | DC_TCTL_AUTONEGENBL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x70))) & ~(0x00000080)))); | |||
| 1289 | dc_apply_fixup(sc, | |||
| 1290 | (media & IFM_GMASK0x00ffff0000000000ULL) == IFM_FDX0x0000010000000000ULL ? | |||
| 1291 | IFM_10_T3|IFM_FDX0x0000010000000000ULL : IFM_10_T3); | |||
| 1292 | DELAY(20000)(*delay_func)(20000); | |||
| 1293 | } | |||
| 1294 | } | |||
| 1295 | } | |||
| 1296 | ||||
| 1297 | /* | |||
| 1298 | * If this is a Davicom DM9102A card with a DM9801 HomePNA | |||
| 1299 | * PHY and we want HomePNA mode, set the portsel bit to turn | |||
| 1300 | * on the external MII port. | |||
| 1301 | */ | |||
| 1302 | if (DC_IS_DAVICOM(sc)(sc->dc_type == 0x8)) { | |||
| 1303 | if (IFM_SUBTYPE(media)((media) & 0x00000000000000ffULL) == IFM_HPNA_117) { | |||
| 1304 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00040000)))); | |||
| 1305 | sc->dc_link = 1; | |||
| 1306 | } else { | |||
| 1307 | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~(0x00040000)))); | |||
| 1308 | } | |||
| 1309 | } | |||
| 1310 | ||||
| 1311 | if ((media & IFM_GMASK0x00ffff0000000000ULL) == IFM_FDX0x0000010000000000ULL) { | |||
| 1312 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00000200)))); | |||
| 1313 | if (sc->dc_pmode == DC_PMODE_SYM0x2 && DC_IS_PNIC(sc)(sc->dc_type == 0xA)) | |||
| 1314 | DC_SETBIT(sc, DC_PN_NWAY, DC_PN_NWAY_DUPLEX)((sc->dc_btag)->write_4((sc->dc_bhandle), (0xB8), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0xB8))) | ( 0x00000100)))); | |||
| 1315 | } else { | |||
| 1316 | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~(0x00000200)))); | |||
| 1317 | if (sc->dc_pmode == DC_PMODE_SYM0x2 && DC_IS_PNIC(sc)(sc->dc_type == 0xA)) | |||
| 1318 | DC_CLRBIT(sc, DC_PN_NWAY, DC_PN_NWAY_DUPLEX)((sc->dc_btag)->write_4((sc->dc_bhandle), (0xB8), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0xB8))) & ~(0x00000100)))); | |||
| 1319 | } | |||
| 1320 | ||||
| 1321 | if (restart) | |||
| 1322 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON|DC_NETCFG_RX_ON)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00002000|0x00000002)))); | |||
| 1323 | } | |||
| 1324 | ||||
| 1325 | void | |||
| 1326 | dc_reset(struct dc_softc *sc) | |||
| 1327 | { | |||
| 1328 | int i; | |||
| 1329 | ||||
| 1330 | DC_SETBIT(sc, DC_BUSCTL, DC_BUSCTL_RESET)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x00), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x00))) | ( 0x00000001)))); | |||
| 1331 | ||||
| 1332 | for (i = 0; i < DC_TIMEOUT1000; i++) { | |||
| 1333 | DELAY(10)(*delay_func)(10); | |||
| 1334 | if (!(CSR_READ_4(sc, DC_BUSCTL)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x00))) & DC_BUSCTL_RESET0x00000001)) | |||
| 1335 | break; | |||
| 1336 | } | |||
| 1337 | ||||
| 1338 | if (DC_IS_ASIX(sc)(sc->dc_type == 0x5) || DC_IS_ADMTEK(sc)(sc->dc_type == 0x6 || sc->dc_type == 0x7) || DC_IS_XIRCOM(sc)(sc->dc_type == 0xB) || | |||
| 1339 | DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD) || DC_IS_CONEXANT(sc)(sc->dc_type == 0xC)) { | |||
| 1340 | DELAY(10000)(*delay_func)(10000); | |||
| 1341 | DC_CLRBIT(sc, DC_BUSCTL, DC_BUSCTL_RESET)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x00), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x00))) & ~(0x00000001)))); | |||
| 1342 | i = 0; | |||
| 1343 | } | |||
| 1344 | ||||
| 1345 | if (i == DC_TIMEOUT1000) | |||
| 1346 | printf("%s: reset never completed!\n", sc->sc_dev.dv_xname); | |||
| 1347 | ||||
| 1348 | /* Wait a little while for the chip to get its brains in order. */ | |||
| 1349 | DELAY(1000)(*delay_func)(1000); | |||
| 1350 | ||||
| 1351 | CSR_WRITE_4(sc, DC_IMR, 0x00000000)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x38), (0x00000000 ))); | |||
| 1352 | CSR_WRITE_4(sc, DC_BUSCTL, 0x00000000)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x00), (0x00000000 ))); | |||
| 1353 | CSR_WRITE_4(sc, DC_NETCFG, 0x00000000)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (0x00000000 ))); | |||
| 1354 | ||||
| 1355 | /* | |||
| 1356 | * Bring the SIA out of reset. In some cases, it looks | |||
| 1357 | * like failing to unreset the SIA soon enough gets it | |||
| 1358 | * into a state where it will never come out of reset | |||
| 1359 | * until we reset the whole chip again. | |||
| 1360 | */ | |||
| 1361 | if (DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD)) { | |||
| 1362 | DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x68), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x68))) | ( 0x00000001)))); | |||
| 1363 | CSR_WRITE_4(sc, DC_10BTCTRL, 0)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x70), (0 ))); | |||
| 1364 | CSR_WRITE_4(sc, DC_WATCHDOG, 0)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (0 ))); | |||
| 1365 | } | |||
| 1366 | ||||
| 1367 | if (sc->dc_type == DC_TYPE_211450xD) | |||
| 1368 | dc_setcfg(sc, IFM_10_T3); | |||
| 1369 | } | |||
| 1370 | ||||
| 1371 | void | |||
| 1372 | dc_apply_fixup(struct dc_softc *sc, uint64_t media) | |||
| 1373 | { | |||
| 1374 | struct dc_mediainfo *m; | |||
| 1375 | u_int8_t *p; | |||
| 1376 | int i; | |||
| 1377 | u_int32_t reg; | |||
| 1378 | ||||
| 1379 | m = sc->dc_mi; | |||
| 1380 | ||||
| 1381 | while (m != NULL((void *)0)) { | |||
| 1382 | if (m->dc_media == media) | |||
| 1383 | break; | |||
| 1384 | m = m->dc_nextdc_ptr2; | |||
| 1385 | } | |||
| 1386 | ||||
| 1387 | if (m == NULL((void *)0)) | |||
| 1388 | return; | |||
| 1389 | ||||
| 1390 | for (i = 0, p = m->dc_reset_ptr; i < m->dc_reset_len; i++, p += 2) { | |||
| 1391 | reg = (p[0] | (p[1] << 8)) << 16; | |||
| 1392 | CSR_WRITE_4(sc, DC_WATCHDOG, reg)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (reg ))); | |||
| 1393 | } | |||
| 1394 | ||||
| 1395 | for (i = 0, p = m->dc_gp_ptr; i < m->dc_gp_len; i++, p += 2) { | |||
| 1396 | reg = (p[0] | (p[1] << 8)) << 16; | |||
| 1397 | CSR_WRITE_4(sc, DC_WATCHDOG, reg)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (reg ))); | |||
| 1398 | } | |||
| 1399 | } | |||
| 1400 | ||||
| 1401 | void | |||
| 1402 | dc_decode_leaf_sia(struct dc_softc *sc, struct dc_eblock_sia *l) | |||
| 1403 | { | |||
| 1404 | struct dc_mediainfo *m; | |||
| 1405 | ||||
| 1406 | m = malloc(sizeof(*m), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008); | |||
| 1407 | if (m == NULL((void *)0)) | |||
| 1408 | return; | |||
| 1409 | switch (l->dc_sia_code & ~DC_SIA_CODE_EXT0x40) { | |||
| 1410 | case DC_SIA_CODE_10BT0x00: | |||
| 1411 | m->dc_media = IFM_10_T3; | |||
| 1412 | break; | |||
| 1413 | case DC_SIA_CODE_10BT_FDX0x04: | |||
| 1414 | m->dc_media = IFM_10_T3|IFM_FDX0x0000010000000000ULL; | |||
| 1415 | break; | |||
| 1416 | case DC_SIA_CODE_10B20x01: | |||
| 1417 | m->dc_media = IFM_10_24; | |||
| 1418 | break; | |||
| 1419 | case DC_SIA_CODE_10B50x02: | |||
| 1420 | m->dc_media = IFM_10_55; | |||
| 1421 | break; | |||
| 1422 | default: | |||
| 1423 | break; | |||
| 1424 | } | |||
| 1425 | ||||
| 1426 | /* | |||
| 1427 | * We need to ignore CSR13, CSR14, CSR15 for SIA mode. | |||
| 1428 | * Things apparently already work for cards that do | |||
| 1429 | * supply Media Specific Data. | |||
| 1430 | */ | |||
| 1431 | if (l->dc_sia_code & DC_SIA_CODE_EXT0x40) { | |||
| 1432 | m->dc_gp_len = 2; | |||
| 1433 | m->dc_gp_ptr = | |||
| 1434 | (u_int8_t *)&l->dc_un.dc_sia_ext.dc_sia_gpio_ctl; | |||
| 1435 | } else { | |||
| 1436 | m->dc_gp_len = 2; | |||
| 1437 | m->dc_gp_ptr = | |||
| 1438 | (u_int8_t *)&l->dc_un.dc_sia_noext.dc_sia_gpio_ctl; | |||
| 1439 | } | |||
| 1440 | ||||
| 1441 | m->dc_nextdc_ptr2 = sc->dc_mi; | |||
| 1442 | sc->dc_mi = m; | |||
| 1443 | ||||
| 1444 | sc->dc_pmode = DC_PMODE_SIA0x3; | |||
| 1445 | } | |||
| 1446 | ||||
| 1447 | void | |||
| 1448 | dc_decode_leaf_sym(struct dc_softc *sc, struct dc_eblock_sym *l) | |||
| 1449 | { | |||
| 1450 | struct dc_mediainfo *m; | |||
| 1451 | ||||
| 1452 | m = malloc(sizeof(*m), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008); | |||
| 1453 | if (m == NULL((void *)0)) | |||
| 1454 | return; | |||
| 1455 | if (l->dc_sym_code == DC_SYM_CODE_100BT0x03) | |||
| 1456 | m->dc_media = IFM_100_TX6; | |||
| 1457 | ||||
| 1458 | if (l->dc_sym_code == DC_SYM_CODE_100BT_FDX0x05) | |||
| 1459 | m->dc_media = IFM_100_TX6|IFM_FDX0x0000010000000000ULL; | |||
| 1460 | ||||
| 1461 | m->dc_gp_len = 2; | |||
| 1462 | m->dc_gp_ptr = (u_int8_t *)&l->dc_sym_gpio_ctl; | |||
| 1463 | ||||
| 1464 | m->dc_nextdc_ptr2 = sc->dc_mi; | |||
| 1465 | sc->dc_mi = m; | |||
| 1466 | ||||
| 1467 | sc->dc_pmode = DC_PMODE_SYM0x2; | |||
| 1468 | } | |||
| 1469 | ||||
| 1470 | void | |||
| 1471 | dc_decode_leaf_mii(struct dc_softc *sc, struct dc_eblock_mii *l) | |||
| 1472 | { | |||
| 1473 | u_int8_t *p; | |||
| 1474 | struct dc_mediainfo *m; | |||
| 1475 | ||||
| 1476 | m = malloc(sizeof(*m), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008); | |||
| 1477 | if (m == NULL((void *)0)) | |||
| 1478 | return; | |||
| 1479 | /* We abuse IFM_AUTO to represent MII. */ | |||
| 1480 | m->dc_media = IFM_AUTO0ULL; | |||
| 1481 | m->dc_gp_len = l->dc_gpr_len; | |||
| 1482 | ||||
| 1483 | p = (u_int8_t *)l; | |||
| 1484 | p += sizeof(struct dc_eblock_mii); | |||
| 1485 | m->dc_gp_ptr = p; | |||
| 1486 | p += 2 * l->dc_gpr_len; | |||
| 1487 | m->dc_reset_len = *p; | |||
| 1488 | p++; | |||
| 1489 | m->dc_reset_ptr = p; | |||
| 1490 | ||||
| 1491 | m->dc_nextdc_ptr2 = sc->dc_mi; | |||
| 1492 | sc->dc_mi = m; | |||
| 1493 | } | |||
| 1494 | ||||
| 1495 | void | |||
| 1496 | dc_read_srom(struct dc_softc *sc, int bits) | |||
| 1497 | { | |||
| 1498 | sc->dc_sromsize = 2 << bits; | |||
| 1499 | sc->dc_srom = malloc(sc->dc_sromsize, M_DEVBUF2, M_NOWAIT0x0002); | |||
| 1500 | if (sc->dc_srom == NULL((void *)0)) | |||
| 1501 | return; | |||
| 1502 | dc_read_eeprom(sc, (caddr_t)sc->dc_srom, 0, (sc->dc_sromsize / 2), 0); | |||
| 1503 | } | |||
| 1504 | ||||
| 1505 | void | |||
| 1506 | dc_parse_21143_srom(struct dc_softc *sc) | |||
| 1507 | { | |||
| 1508 | struct dc_leaf_hdr *lhdr; | |||
| 1509 | struct dc_eblock_hdr *hdr; | |||
| 1510 | int have_mii, i, loff; | |||
| 1511 | char *ptr; | |||
| 1512 | ||||
| 1513 | have_mii = 0; | |||
| 1514 | loff = sc->dc_srom[27]; | |||
| 1515 | lhdr = (struct dc_leaf_hdr *)&(sc->dc_srom[loff]); | |||
| 1516 | ||||
| 1517 | ptr = (char *)lhdr; | |||
| 1518 | ptr += sizeof(struct dc_leaf_hdr) - 1; | |||
| 1519 | /* | |||
| 1520 | * Look if we got a MII media block. | |||
| 1521 | */ | |||
| 1522 | for (i = 0; i < lhdr->dc_mcnt; i++) { | |||
| 1523 | hdr = (struct dc_eblock_hdr *)ptr; | |||
| 1524 | if (hdr->dc_type == DC_EBLOCK_MII0x0003) | |||
| 1525 | have_mii++; | |||
| 1526 | ||||
| 1527 | ptr += (hdr->dc_len & 0x7F); | |||
| 1528 | ptr++; | |||
| 1529 | } | |||
| 1530 | ||||
| 1531 | /* | |||
| 1532 | * Do the same thing again. Only use SIA and SYM media | |||
| 1533 | * blocks if no MII media block is available. | |||
| 1534 | */ | |||
| 1535 | ptr = (char *)lhdr; | |||
| 1536 | ptr += sizeof(struct dc_leaf_hdr) - 1; | |||
| 1537 | for (i = 0; i < lhdr->dc_mcnt; i++) { | |||
| 1538 | hdr = (struct dc_eblock_hdr *)ptr; | |||
| 1539 | switch(hdr->dc_type) { | |||
| 1540 | case DC_EBLOCK_MII0x0003: | |||
| 1541 | dc_decode_leaf_mii(sc, (struct dc_eblock_mii *)hdr); | |||
| 1542 | break; | |||
| 1543 | case DC_EBLOCK_SIA0x0002: | |||
| 1544 | if (! have_mii) | |||
| 1545 | dc_decode_leaf_sia(sc, | |||
| 1546 | (struct dc_eblock_sia *)hdr); | |||
| 1547 | break; | |||
| 1548 | case DC_EBLOCK_SYM0x0004: | |||
| 1549 | if (! have_mii) | |||
| 1550 | dc_decode_leaf_sym(sc, | |||
| 1551 | (struct dc_eblock_sym *)hdr); | |||
| 1552 | break; | |||
| 1553 | default: | |||
| 1554 | /* Don't care. Yet. */ | |||
| 1555 | break; | |||
| 1556 | } | |||
| 1557 | ptr += (hdr->dc_len & 0x7F); | |||
| 1558 | ptr++; | |||
| 1559 | } | |||
| 1560 | } | |||
| 1561 | ||||
| 1562 | /* | |||
| 1563 | * Attach the interface. Allocate softc structures, do ifmedia | |||
| 1564 | * setup and ethernet/BPF attach. | |||
| 1565 | */ | |||
| 1566 | void | |||
| 1567 | dc_attach(struct dc_softc *sc) | |||
| 1568 | { | |||
| 1569 | struct ifnet *ifp; | |||
| 1570 | int mac_offset, tmp, i; | |||
| 1571 | u_int32_t reg; | |||
| 1572 | ||||
| 1573 | /* | |||
| 1574 | * Get station address from the EEPROM. | |||
| 1575 | */ | |||
| 1576 | if (sc->sc_hasmac) | |||
| 1577 | goto hasmac; | |||
| 1578 | ||||
| 1579 | switch(sc->dc_type) { | |||
| 1580 | case DC_TYPE_987130x1: | |||
| 1581 | case DC_TYPE_98713A0x2: | |||
| 1582 | case DC_TYPE_987x50x3: | |||
| 1583 | case DC_TYPE_PNICII0x9: | |||
| 1584 | dc_read_eeprom(sc, (caddr_t)&mac_offset, | |||
| 1585 | (DC_EE_NODEADDR_OFFSET0x70 / 2), 1, 0); | |||
| 1586 | dc_read_eeprom(sc, (caddr_t)&sc->sc_arpcom.ac_enaddr, | |||
| 1587 | (mac_offset / 2), 3, 0); | |||
| 1588 | break; | |||
| 1589 | case DC_TYPE_PNIC0xA: | |||
| 1590 | dc_read_eeprom(sc, (caddr_t)&sc->sc_arpcom.ac_enaddr, 0, 3, 1); | |||
| 1591 | break; | |||
| 1592 | case DC_TYPE_DM91020x8: | |||
| 1593 | case DC_TYPE_211430x4: | |||
| 1594 | case DC_TYPE_211450xD: | |||
| 1595 | case DC_TYPE_ASIX0x5: | |||
| 1596 | dc_read_eeprom(sc, (caddr_t)&sc->sc_arpcom.ac_enaddr, | |||
| 1597 | DC_EE_NODEADDR10, 3, 0); | |||
| 1598 | break; | |||
| 1599 | case DC_TYPE_AL9810x6: | |||
| 1600 | case DC_TYPE_AN9830x7: | |||
| 1601 | reg = CSR_READ_4(sc, DC_AL_PAR0)((sc->dc_btag)->read_4((sc->dc_bhandle), (0xA4))); | |||
| 1602 | sc->sc_arpcom.ac_enaddr[0] = (reg & 0xff); | |||
| 1603 | sc->sc_arpcom.ac_enaddr[1] = (reg >> 8) & 0xff; | |||
| 1604 | sc->sc_arpcom.ac_enaddr[2] = (reg >> 16) & 0xff; | |||
| 1605 | sc->sc_arpcom.ac_enaddr[3] = (reg >> 24) & 0xff; | |||
| 1606 | reg = CSR_READ_4(sc, DC_AL_PAR1)((sc->dc_btag)->read_4((sc->dc_bhandle), (0xA8))); | |||
| 1607 | sc->sc_arpcom.ac_enaddr[4] = (reg & 0xff); | |||
| 1608 | sc->sc_arpcom.ac_enaddr[5] = (reg >> 8) & 0xff; | |||
| 1609 | break; | |||
| 1610 | case DC_TYPE_CONEXANT0xC: | |||
| 1611 | bcopy(&sc->dc_srom + DC_CONEXANT_EE_NODEADDR0x19A, | |||
| 1612 | &sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN6); | |||
| 1613 | break; | |||
| 1614 | case DC_TYPE_XIRCOM0xB: | |||
| 1615 | /* Some newer units have the MAC at offset 8 */ | |||
| 1616 | dc_read_eeprom(sc, (caddr_t)&sc->sc_arpcom.ac_enaddr, 8, 3, 0); | |||
| 1617 | ||||
| 1618 | if (sc->sc_arpcom.ac_enaddr[0] == 0x00 && | |||
| 1619 | sc->sc_arpcom.ac_enaddr[1] == 0x10 && | |||
| 1620 | sc->sc_arpcom.ac_enaddr[2] == 0xa4) | |||
| 1621 | break; | |||
| 1622 | if (sc->sc_arpcom.ac_enaddr[0] == 0x00 && | |||
| 1623 | sc->sc_arpcom.ac_enaddr[1] == 0x80 && | |||
| 1624 | sc->sc_arpcom.ac_enaddr[2] == 0xc7) | |||
| 1625 | break; | |||
| 1626 | dc_read_eeprom(sc, (caddr_t)&sc->sc_arpcom.ac_enaddr, 3, 3, 0); | |||
| 1627 | break; | |||
| 1628 | default: | |||
| 1629 | dc_read_eeprom(sc, (caddr_t)&sc->sc_arpcom.ac_enaddr, | |||
| 1630 | DC_EE_NODEADDR10, 3, 0); | |||
| 1631 | break; | |||
| 1632 | } | |||
| 1633 | hasmac: | |||
| 1634 | ||||
| 1635 | if (bus_dmamem_alloc(sc->sc_dmat, sizeof(struct dc_list_data),(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), (sizeof (struct dc_list_data)), ((1 << 12)), (0), (sc->sc_listseg ), (1), (&sc->sc_listnseg), (0x0001 | 0x1000)) | |||
| 1636 | PAGE_SIZE, 0, sc->sc_listseg, 1, &sc->sc_listnseg,(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), (sizeof (struct dc_list_data)), ((1 << 12)), (0), (sc->sc_listseg ), (1), (&sc->sc_listnseg), (0x0001 | 0x1000)) | |||
| 1637 | BUS_DMA_NOWAIT | BUS_DMA_ZERO)(*(sc->sc_dmat)->_dmamem_alloc)((sc->sc_dmat), (sizeof (struct dc_list_data)), ((1 << 12)), (0), (sc->sc_listseg ), (1), (&sc->sc_listnseg), (0x0001 | 0x1000)) != 0) { | |||
| 1638 | printf(": can't alloc list mem\n"); | |||
| 1639 | goto fail; | |||
| 1640 | } | |||
| 1641 | if (bus_dmamem_map(sc->sc_dmat, sc->sc_listseg, sc->sc_listnseg,(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (sc-> sc_listseg), (sc->sc_listnseg), (sizeof(struct dc_list_data )), (&sc->sc_listkva), (0x0001)) | |||
| 1642 | sizeof(struct dc_list_data), &sc->sc_listkva,(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (sc-> sc_listseg), (sc->sc_listnseg), (sizeof(struct dc_list_data )), (&sc->sc_listkva), (0x0001)) | |||
| 1643 | BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamem_map)((sc->sc_dmat), (sc-> sc_listseg), (sc->sc_listnseg), (sizeof(struct dc_list_data )), (&sc->sc_listkva), (0x0001)) != 0) { | |||
| 1644 | printf(": can't map list mem\n"); | |||
| 1645 | goto fail; | |||
| 1646 | } | |||
| 1647 | if (bus_dmamap_create(sc->sc_dmat, sizeof(struct dc_list_data), 1,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (sizeof (struct dc_list_data)), (1), (sizeof(struct dc_list_data)), ( 0), (0x0001), (&sc->sc_listmap)) | |||
| 1648 | sizeof(struct dc_list_data), 0, BUS_DMA_NOWAIT,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (sizeof (struct dc_list_data)), (1), (sizeof(struct dc_list_data)), ( 0), (0x0001), (&sc->sc_listmap)) | |||
| 1649 | &sc->sc_listmap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), (sizeof (struct dc_list_data)), (1), (sizeof(struct dc_list_data)), ( 0), (0x0001), (&sc->sc_listmap)) != 0) { | |||
| 1650 | printf(": can't alloc list map\n"); | |||
| 1651 | goto fail; | |||
| 1652 | } | |||
| 1653 | if (bus_dmamap_load(sc->sc_dmat, sc->sc_listmap, sc->sc_listkva,(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (sc-> sc_listmap), (sc->sc_listkva), (sizeof(struct dc_list_data )), (((void *)0)), (0x0001)) | |||
| 1654 | sizeof(struct dc_list_data), NULL, BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load)((sc->sc_dmat), (sc-> sc_listmap), (sc->sc_listkva), (sizeof(struct dc_list_data )), (((void *)0)), (0x0001)) != 0) { | |||
| 1655 | printf(": can't load list map\n"); | |||
| 1656 | goto fail; | |||
| 1657 | } | |||
| 1658 | sc->dc_ldata = (struct dc_list_data *)sc->sc_listkva; | |||
| 1659 | ||||
| 1660 | for (i = 0; i < DC_RX_LIST_CNT64; i++) { | |||
| 1661 | if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&sc->dc_cdata .dc_rx_chain[i].sd_map)) | |||
| 1662 | 0, BUS_DMA_NOWAIT,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&sc->dc_cdata .dc_rx_chain[i].sd_map)) | |||
| 1663 | &sc->dc_cdata.dc_rx_chain[i].sd_map)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&sc->dc_cdata .dc_rx_chain[i].sd_map)) != 0) { | |||
| 1664 | printf(": can't create rx map\n"); | |||
| 1665 | return; | |||
| 1666 | } | |||
| 1667 | } | |||
| 1668 | if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&sc->sc_rx_sparemap )) | |||
| 1669 | BUS_DMA_NOWAIT, &sc->sc_rx_sparemap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), (1), ((1 << 11)), (0), (0x0001), (&sc->sc_rx_sparemap )) != 0) { | |||
| 1670 | printf(": can't create rx spare map\n"); | |||
| 1671 | return; | |||
| 1672 | } | |||
| 1673 | ||||
| 1674 | for (i = 0; i < DC_TX_LIST_CNT256; i++) { | |||
| 1675 | if (bus_dmamap_create(sc->sc_dmat, MCLBYTES,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), ((sc->dc_flags & 0x00000002) ? 1 : 256 - 5), (( 1 << 11)), (0), (0x0001), (&sc->dc_cdata.dc_tx_chain [i].sd_map)) | |||
| 1676 | (sc->dc_flags & DC_TX_COALESCE) ? 1 : DC_TX_LIST_CNT - 5,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), ((sc->dc_flags & 0x00000002) ? 1 : 256 - 5), (( 1 << 11)), (0), (0x0001), (&sc->dc_cdata.dc_tx_chain [i].sd_map)) | |||
| 1677 | MCLBYTES, 0, BUS_DMA_NOWAIT,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), ((sc->dc_flags & 0x00000002) ? 1 : 256 - 5), (( 1 << 11)), (0), (0x0001), (&sc->dc_cdata.dc_tx_chain [i].sd_map)) | |||
| 1678 | &sc->dc_cdata.dc_tx_chain[i].sd_map)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), ((sc->dc_flags & 0x00000002) ? 1 : 256 - 5), (( 1 << 11)), (0), (0x0001), (&sc->dc_cdata.dc_tx_chain [i].sd_map)) != 0) { | |||
| 1679 | printf(": can't create tx map\n"); | |||
| 1680 | return; | |||
| 1681 | } | |||
| 1682 | } | |||
| 1683 | if (bus_dmamap_create(sc->sc_dmat, MCLBYTES,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), ((sc->dc_flags & 0x00000002) ? 1 : 256 - 5), (( 1 << 11)), (0), (0x0001), (&sc->sc_tx_sparemap)) | |||
| 1684 | (sc->dc_flags & DC_TX_COALESCE) ? 1 : DC_TX_LIST_CNT - 5,(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), ((sc->dc_flags & 0x00000002) ? 1 : 256 - 5), (( 1 << 11)), (0), (0x0001), (&sc->sc_tx_sparemap)) | |||
| 1685 | MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_tx_sparemap)(*(sc->sc_dmat)->_dmamap_create)((sc->sc_dmat), ((1 << 11)), ((sc->dc_flags & 0x00000002) ? 1 : 256 - 5), (( 1 << 11)), (0), (0x0001), (&sc->sc_tx_sparemap)) != 0) { | |||
| 1686 | printf(": can't create tx spare map\n"); | |||
| 1687 | return; | |||
| 1688 | } | |||
| 1689 | ||||
| 1690 | /* | |||
| 1691 | * A 21143 or clone chip was detected. Inform the world. | |||
| 1692 | */ | |||
| 1693 | printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); | |||
| 1694 | ||||
| 1695 | ifp = &sc->sc_arpcom.ac_if; | |||
| 1696 | ifp->if_softc = sc; | |||
| 1697 | ifp->if_flags = IFF_BROADCAST0x2 | IFF_SIMPLEX0x800 | IFF_MULTICAST0x8000; | |||
| 1698 | ifp->if_ioctl = dc_ioctl; | |||
| 1699 | ifp->if_start = dc_start; | |||
| 1700 | ifp->if_watchdog = dc_watchdog; | |||
| 1701 | ifq_set_maxlen(&ifp->if_snd, DC_TX_LIST_CNT - 1)((&ifp->if_snd)->ifq_maxlen = (256 - 1)); | |||
| 1702 | bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ16); | |||
| 1703 | ||||
| 1704 | ifp->if_capabilitiesif_data.ifi_capabilities = IFCAP_VLAN_MTU0x00000010; | |||
| 1705 | ||||
| 1706 | /* Do MII setup. If this is a 21143, check for a PHY on the | |||
| 1707 | * MII bus after applying any necessary fixups to twiddle the | |||
| 1708 | * GPIO bits. If we don't end up finding a PHY, restore the | |||
| 1709 | * old selection (SIA only or SIA/SYM) and attach the dcphy | |||
| 1710 | * driver instead. | |||
| 1711 | */ | |||
| 1712 | if (DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD)) { | |||
| 1713 | dc_apply_fixup(sc, IFM_AUTO0ULL); | |||
| 1714 | tmp = sc->dc_pmode; | |||
| 1715 | sc->dc_pmode = DC_PMODE_MII0x1; | |||
| 1716 | } | |||
| 1717 | ||||
| 1718 | /* | |||
| 1719 | * Setup General Purpose port mode and data so the tulip can talk | |||
| 1720 | * to the MII. This needs to be done before mii_attach so that | |||
| 1721 | * we can actually see them. | |||
| 1722 | */ | |||
| 1723 | if (DC_IS_XIRCOM(sc)(sc->dc_type == 0xB)) { | |||
| 1724 | CSR_WRITE_4(sc, DC_SIAGP, DC_SIAGP_WRITE_EN | DC_SIAGP_INT1_EN |((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (0x08000000 | 0x02000000 | 0x00040000 | 0x00010000))) | |||
| 1725 | DC_SIAGP_MD_GP2_OUTPUT | DC_SIAGP_MD_GP0_OUTPUT)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (0x08000000 | 0x02000000 | 0x00040000 | 0x00010000))); | |||
| 1726 | DELAY(10)(*delay_func)(10); | |||
| 1727 | CSR_WRITE_4(sc, DC_SIAGP, DC_SIAGP_INT1_EN |((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (0x02000000 | 0x00040000 | 0x00010000))) | |||
| 1728 | DC_SIAGP_MD_GP2_OUTPUT | DC_SIAGP_MD_GP0_OUTPUT)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (0x02000000 | 0x00040000 | 0x00010000))); | |||
| 1729 | DELAY(10)(*delay_func)(10); | |||
| 1730 | } | |||
| 1731 | ||||
| 1732 | sc->sc_mii.mii_ifp = ifp; | |||
| 1733 | sc->sc_mii.mii_readreg = dc_miibus_readreg; | |||
| 1734 | sc->sc_mii.mii_writereg = dc_miibus_writereg; | |||
| 1735 | sc->sc_mii.mii_statchg = dc_miibus_statchg; | |||
| 1736 | ifmedia_init(&sc->sc_mii.mii_media, 0, dc_ifmedia_upd, dc_ifmedia_sts); | |||
| 1737 | mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY-1, | |||
| 1738 | MII_OFFSET_ANY-1, 0); | |||
| 1739 | ||||
| 1740 | if (DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD)) { | |||
| 1741 | if (LIST_EMPTY(&sc->sc_mii.mii_phys)(((&sc->sc_mii.mii_phys)->lh_first) == ((void *)0))) { | |||
| 1742 | sc->dc_pmode = tmp; | |||
| 1743 | if (sc->dc_pmode != DC_PMODE_SIA0x3) | |||
| 1744 | sc->dc_pmode = DC_PMODE_SYM0x2; | |||
| 1745 | sc->dc_flags |= DC_21143_NWAY0x00000800; | |||
| 1746 | if (sc->dc_flags & DC_MOMENCO_BOTCH0x00020000) | |||
| 1747 | sc->dc_pmode = DC_PMODE_MII0x1; | |||
| 1748 | mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, | |||
| 1749 | MII_PHY_ANY-1, MII_OFFSET_ANY-1, 0); | |||
| 1750 | } else { | |||
| 1751 | /* we have a PHY, so we must clear this bit */ | |||
| 1752 | sc->dc_flags &= ~DC_TULIP_LEDS0x00004000; | |||
| 1753 | } | |||
| 1754 | } | |||
| 1755 | ||||
| 1756 | if (LIST_EMPTY(&sc->sc_mii.mii_phys)(((&sc->sc_mii.mii_phys)->lh_first) == ((void *)0))) { | |||
| 1757 | ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER0x0000000000000100ULL|IFM_NONE2ULL, 0, NULL((void *)0)); | |||
| 1758 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER0x0000000000000100ULL|IFM_NONE2ULL); | |||
| 1759 | printf("%s: MII without any PHY!\n", sc->sc_dev.dv_xname); | |||
| 1760 | } else if (sc->dc_type == DC_TYPE_211450xD) { | |||
| 1761 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER0x0000000000000100ULL|IFM_10_T3); | |||
| 1762 | } else | |||
| 1763 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER0x0000000000000100ULL|IFM_AUTO0ULL); | |||
| 1764 | ||||
| 1765 | if (DC_IS_DAVICOM(sc)(sc->dc_type == 0x8) && sc->dc_revision >= DC_REVISION_DM9102A0x30) | |||
| 1766 | ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER0x0000000000000100ULL|IFM_HPNA_117,0,NULL((void *)0)); | |||
| 1767 | ||||
| 1768 | if (DC_IS_ADMTEK(sc)(sc->dc_type == 0x6 || sc->dc_type == 0x7)) { | |||
| 1769 | /* | |||
| 1770 | * Set automatic TX underrun recovery for the ADMtek chips | |||
| 1771 | */ | |||
| 1772 | DC_SETBIT(sc, DC_AL_CR, DC_AL_CR_ATUR)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x88), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x88))) | ( 0x00000001)))); | |||
| 1773 | } | |||
| 1774 | ||||
| 1775 | /* | |||
| 1776 | * Call MI attach routines. | |||
| 1777 | */ | |||
| 1778 | if_attach(ifp); | |||
| 1779 | ether_ifattach(ifp); | |||
| 1780 | ||||
| 1781 | fail: | |||
| 1782 | return; | |||
| 1783 | } | |||
| 1784 | ||||
| 1785 | /* | |||
| 1786 | * Initialize the transmit descriptors. | |||
| 1787 | */ | |||
| 1788 | int | |||
| 1789 | dc_list_tx_init(struct dc_softc *sc) | |||
| 1790 | { | |||
| 1791 | struct dc_chain_data *cd; | |||
| 1792 | struct dc_list_data *ld; | |||
| 1793 | int i; | |||
| 1794 | bus_addr_t next; | |||
| 1795 | ||||
| 1796 | cd = &sc->dc_cdata; | |||
| 1797 | ld = sc->dc_ldata; | |||
| 1798 | for (i = 0; i < DC_TX_LIST_CNT256; i++) { | |||
| 1799 | next = sc->sc_listmap->dm_segs[0].ds_addr; | |||
| 1800 | if (i == (DC_TX_LIST_CNT256 - 1)) | |||
| 1801 | next += | |||
| 1802 | offsetof(struct dc_list_data, dc_tx_list[0])__builtin_offsetof(struct dc_list_data, dc_tx_list[0]); | |||
| 1803 | else | |||
| 1804 | next += | |||
| 1805 | offsetof(struct dc_list_data, dc_tx_list[i + 1])__builtin_offsetof(struct dc_list_data, dc_tx_list[i + 1]); | |||
| 1806 | cd->dc_tx_chain[i].sd_mbuf = NULL((void *)0); | |||
| 1807 | ld->dc_tx_list[i].dc_datadc_ptr1 = htole32(0)((__uint32_t)(0)); | |||
| 1808 | ld->dc_tx_list[i].dc_ctl = htole32(0)((__uint32_t)(0)); | |||
| 1809 | ld->dc_tx_list[i].dc_nextdc_ptr2 = htole32(next)((__uint32_t)(next)); | |||
| 1810 | } | |||
| 1811 | ||||
| 1812 | cd->dc_tx_prod = cd->dc_tx_cons = cd->dc_tx_cnt = 0; | |||
| 1813 | ||||
| 1814 | return (0); | |||
| 1815 | } | |||
| 1816 | ||||
| 1817 | ||||
| 1818 | /* | |||
| 1819 | * Initialize the RX descriptors and allocate mbufs for them. Note that | |||
| 1820 | * we arrange the descriptors in a closed ring, so that the last descriptor | |||
| 1821 | * points back to the first. | |||
| 1822 | */ | |||
| 1823 | int | |||
| 1824 | dc_list_rx_init(struct dc_softc *sc) | |||
| 1825 | { | |||
| 1826 | struct dc_chain_data *cd; | |||
| 1827 | struct dc_list_data *ld; | |||
| 1828 | int i; | |||
| 1829 | bus_addr_t next; | |||
| 1830 | ||||
| 1831 | cd = &sc->dc_cdata; | |||
| 1832 | ld = sc->dc_ldata; | |||
| 1833 | ||||
| 1834 | for (i = 0; i < DC_RX_LIST_CNT64; i++) { | |||
| 1835 | if (dc_newbuf(sc, i, NULL((void *)0)) == ENOBUFS55) | |||
| 1836 | return (ENOBUFS55); | |||
| 1837 | next = sc->sc_listmap->dm_segs[0].ds_addr; | |||
| 1838 | if (i == (DC_RX_LIST_CNT64 - 1)) | |||
| 1839 | next += | |||
| 1840 | offsetof(struct dc_list_data, dc_rx_list[0])__builtin_offsetof(struct dc_list_data, dc_rx_list[0]); | |||
| 1841 | else | |||
| 1842 | next += | |||
| 1843 | offsetof(struct dc_list_data, dc_rx_list[i + 1])__builtin_offsetof(struct dc_list_data, dc_rx_list[i + 1]); | |||
| 1844 | ld->dc_rx_list[i].dc_nextdc_ptr2 = htole32(next)((__uint32_t)(next)); | |||
| 1845 | } | |||
| 1846 | ||||
| 1847 | cd->dc_rx_prod = 0; | |||
| 1848 | ||||
| 1849 | return (0); | |||
| 1850 | } | |||
| 1851 | ||||
| 1852 | /* | |||
| 1853 | * Initialize an RX descriptor and attach an MBUF cluster. | |||
| 1854 | */ | |||
| 1855 | int | |||
| 1856 | dc_newbuf(struct dc_softc *sc, int i, struct mbuf *m) | |||
| 1857 | { | |||
| 1858 | struct mbuf *m_new = NULL((void *)0); | |||
| 1859 | struct dc_desc *c; | |||
| 1860 | bus_dmamap_t map; | |||
| 1861 | ||||
| 1862 | c = &sc->dc_ldata->dc_rx_list[i]; | |||
| 1863 | ||||
| 1864 | if (m == NULL((void *)0)) { | |||
| 1865 | MGETHDR(m_new, M_DONTWAIT, MT_DATA)m_new = m_gethdr((0x0002), (1)); | |||
| 1866 | if (m_new == NULL((void *)0)) | |||
| 1867 | return (ENOBUFS55); | |||
| 1868 | ||||
| 1869 | MCLGET(m_new, M_DONTWAIT)(void) m_clget((m_new), (0x0002), (1 << 11)); | |||
| 1870 | if (!(m_new->m_flagsm_hdr.mh_flags & M_EXT0x0001)) { | |||
| 1871 | m_freem(m_new); | |||
| 1872 | return (ENOBUFS55); | |||
| 1873 | } | |||
| 1874 | m_new->m_lenm_hdr.mh_len = m_new->m_pkthdrM_dat.MH.MH_pkthdr.len = MCLBYTES(1 << 11); | |||
| 1875 | if (bus_dmamap_load_mbuf(sc->sc_dmat, sc->sc_rx_sparemap,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( sc->sc_rx_sparemap), (m_new), (0x0001)) | |||
| 1876 | m_new, BUS_DMA_NOWAIT)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( sc->sc_rx_sparemap), (m_new), (0x0001)) != 0) { | |||
| 1877 | m_freem(m_new); | |||
| 1878 | return (ENOBUFS55); | |||
| 1879 | } | |||
| 1880 | map = sc->dc_cdata.dc_rx_chain[i].sd_map; | |||
| 1881 | sc->dc_cdata.dc_rx_chain[i].sd_map = sc->sc_rx_sparemap; | |||
| 1882 | sc->sc_rx_sparemap = map; | |||
| 1883 | } else { | |||
| 1884 | /* | |||
| 1885 | * We're re-using a previously allocated mbuf; | |||
| 1886 | * be sure to re-init pointers and lengths to | |||
| 1887 | * default values. | |||
| 1888 | */ | |||
| 1889 | m_new = m; | |||
| 1890 | m_new->m_lenm_hdr.mh_len = m_new->m_pkthdrM_dat.MH.MH_pkthdr.len = MCLBYTES(1 << 11); | |||
| 1891 | m_new->m_datam_hdr.mh_data = m_new->m_extM_dat.MH.MH_dat.MH_ext.ext_buf; | |||
| 1892 | } | |||
| 1893 | ||||
| 1894 | m_adj(m_new, sizeof(u_int64_t)); | |||
| 1895 | ||||
| 1896 | /* | |||
| 1897 | * If this is a PNIC chip, zero the buffer. This is part | |||
| 1898 | * of the workaround for the receive bug in the 82c168 and | |||
| 1899 | * 82c169 chips. | |||
| 1900 | */ | |||
| 1901 | if (sc->dc_flags & DC_PNIC_RX_BUG_WAR0x00000040) | |||
| 1902 | bzero(mtod(m_new, char *), m_new->m_len)__builtin_bzero((((char *)((m_new)->m_hdr.mh_data))), (m_new ->m_hdr.mh_len)); | |||
| 1903 | ||||
| 1904 | bus_dmamap_sync(sc->sc_dmat, sc->dc_cdata.dc_rx_chain[i].sd_map, 0,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> dc_cdata.dc_rx_chain[i].sd_map), (0), (sc->dc_cdata.dc_rx_chain [i].sd_map->dm_mapsize), (0x01)) | |||
| 1905 | sc->dc_cdata.dc_rx_chain[i].sd_map->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> dc_cdata.dc_rx_chain[i].sd_map), (0), (sc->dc_cdata.dc_rx_chain [i].sd_map->dm_mapsize), (0x01)) | |||
| 1906 | BUS_DMASYNC_PREREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> dc_cdata.dc_rx_chain[i].sd_map), (0), (sc->dc_cdata.dc_rx_chain [i].sd_map->dm_mapsize), (0x01)); | |||
| 1907 | ||||
| 1908 | sc->dc_cdata.dc_rx_chain[i].sd_mbuf = m_new; | |||
| 1909 | c->dc_datadc_ptr1 = htole32(((__uint32_t)(sc->dc_cdata.dc_rx_chain[i].sd_map->dm_segs [0].ds_addr + sizeof(u_int64_t))) | |||
| 1910 | sc->dc_cdata.dc_rx_chain[i].sd_map->dm_segs[0].ds_addr +((__uint32_t)(sc->dc_cdata.dc_rx_chain[i].sd_map->dm_segs [0].ds_addr + sizeof(u_int64_t))) | |||
| 1911 | sizeof(u_int64_t))((__uint32_t)(sc->dc_cdata.dc_rx_chain[i].sd_map->dm_segs [0].ds_addr + sizeof(u_int64_t))); | |||
| 1912 | c->dc_ctl = htole32(DC_RXCTL_RLINK | ETHER_MAX_DIX_LEN)((__uint32_t)(0x01000000 | 1536)); | |||
| 1913 | c->dc_status = htole32(DC_RXSTAT_OWN)((__uint32_t)(0x80000000)); | |||
| 1914 | ||||
| 1915 | bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_rx_list [i])), (sizeof(struct dc_desc)), (0x01 | 0x04)) | |||
| 1916 | offsetof(struct dc_list_data, dc_rx_list[i]),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_rx_list [i])), (sizeof(struct dc_desc)), (0x01 | 0x04)) | |||
| 1917 | sizeof(struct dc_desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_rx_list [i])), (sizeof(struct dc_desc)), (0x01 | 0x04)) | |||
| 1918 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_rx_list [i])), (sizeof(struct dc_desc)), (0x01 | 0x04)); | |||
| 1919 | ||||
| 1920 | return (0); | |||
| 1921 | } | |||
| 1922 | ||||
| 1923 | /* | |||
| 1924 | * Grrrrr. | |||
| 1925 | * The PNIC chip has a terrible bug in it that manifests itself during | |||
| 1926 | * periods of heavy activity. The exact mode of failure if difficult to | |||
| 1927 | * pinpoint: sometimes it only happens in promiscuous mode, sometimes it | |||
| 1928 | * will happen on slow machines. The bug is that sometimes instead of | |||
| 1929 | * uploading one complete frame during reception, it uploads what looks | |||
| 1930 | * like the entire contents of its FIFO memory. The frame we want is at | |||
| 1931 | * the end of the whole mess, but we never know exactly how much data has | |||
| 1932 | * been uploaded, so salvaging the frame is hard. | |||
| 1933 | * | |||
| 1934 | * There is only one way to do it reliably, and it's disgusting. | |||
| 1935 | * Here's what we know: | |||
| 1936 | * | |||
| 1937 | * - We know there will always be somewhere between one and three extra | |||
| 1938 | * descriptors uploaded. | |||
| 1939 | * | |||
| 1940 | * - We know the desired received frame will always be at the end of the | |||
| 1941 | * total data upload. | |||
| 1942 | * | |||
| 1943 | * - We know the size of the desired received frame because it will be | |||
| 1944 | * provided in the length field of the status word in the last descriptor. | |||
| 1945 | * | |||
| 1946 | * Here's what we do: | |||
| 1947 | * | |||
| 1948 | * - When we allocate buffers for the receive ring, we bzero() them. | |||
| 1949 | * This means that we know that the buffer contents should be all | |||
| 1950 | * zeros, except for data uploaded by the chip. | |||
| 1951 | * | |||
| 1952 | * - We also force the PNIC chip to upload frames that include the | |||
| 1953 | * ethernet CRC at the end. | |||
| 1954 | * | |||
| 1955 | * - We gather all of the bogus frame data into a single buffer. | |||
| 1956 | * | |||
| 1957 | * - We then position a pointer at the end of this buffer and scan | |||
| 1958 | * backwards until we encounter the first non-zero byte of data. | |||
| 1959 | * This is the end of the received frame. We know we will encounter | |||
| 1960 | * some data at the end of the frame because the CRC will always be | |||
| 1961 | * there, so even if the sender transmits a packet of all zeros, | |||
| 1962 | * we won't be fooled. | |||
| 1963 | * | |||
| 1964 | * - We know the size of the actual received frame, so we subtract | |||
| 1965 | * that value from the current pointer location. This brings us | |||
| 1966 | * to the start of the actual received packet. | |||
| 1967 | * | |||
| 1968 | * - We copy this into an mbuf and pass it on, along with the actual | |||
| 1969 | * frame length. | |||
| 1970 | * | |||
| 1971 | * The performance hit is tremendous, but it beats dropping frames all | |||
| 1972 | * the time. | |||
| 1973 | */ | |||
| 1974 | ||||
| 1975 | #define DC_WHOLEFRAME(0x00000200|0x00000100) (DC_RXSTAT_FIRSTFRAG0x00000200|DC_RXSTAT_LASTFRAG0x00000100) | |||
| 1976 | void | |||
| 1977 | dc_pnic_rx_bug_war(struct dc_softc *sc, int idx) | |||
| 1978 | { | |||
| 1979 | struct dc_desc *cur_rx; | |||
| 1980 | struct dc_desc *c = NULL((void *)0); | |||
| 1981 | struct mbuf *m = NULL((void *)0); | |||
| 1982 | unsigned char *ptr; | |||
| 1983 | int i, total_len; | |||
| 1984 | u_int32_t rxstat = 0; | |||
| 1985 | ||||
| 1986 | i = sc->dc_pnic_rx_bug_save; | |||
| 1987 | cur_rx = &sc->dc_ldata->dc_rx_list[idx]; | |||
| 1988 | ptr = sc->dc_pnic_rx_buf; | |||
| 1989 | bzero(ptr, ETHER_MAX_DIX_LEN * 5)__builtin_bzero((ptr), (1536 * 5)); | |||
| 1990 | ||||
| 1991 | /* Copy all the bytes from the bogus buffers. */ | |||
| 1992 | while (1) { | |||
| 1993 | c = &sc->dc_ldata->dc_rx_list[i]; | |||
| 1994 | rxstat = letoh32(c->dc_status)((__uint32_t)(c->dc_status)); | |||
| 1995 | m = sc->dc_cdata.dc_rx_chain[i].sd_mbuf; | |||
| 1996 | bcopy(mtod(m, char *)((char *)((m)->m_hdr.mh_data)), ptr, ETHER_MAX_DIX_LEN1536); | |||
| 1997 | ptr += ETHER_MAX_DIX_LEN1536; | |||
| 1998 | /* If this is the last buffer, break out. */ | |||
| 1999 | if (i == idx || rxstat & DC_RXSTAT_LASTFRAG0x00000100) | |||
| 2000 | break; | |||
| 2001 | dc_newbuf(sc, i, m); | |||
| 2002 | DC_INC(i, DC_RX_LIST_CNT)(i) = (i + 1) % 64; | |||
| 2003 | } | |||
| 2004 | ||||
| 2005 | /* Find the length of the actual receive frame. */ | |||
| 2006 | total_len = DC_RXBYTES(rxstat)((rxstat & 0x3FFF0000) >> 16); | |||
| 2007 | ||||
| 2008 | /* Scan backwards until we hit a non-zero byte. */ | |||
| 2009 | while(*ptr == 0x00) | |||
| 2010 | ptr--; | |||
| 2011 | ||||
| 2012 | /* Round off. */ | |||
| 2013 | if ((unsigned long)(ptr) & 0x3) | |||
| 2014 | ptr -= 1; | |||
| 2015 | ||||
| 2016 | /* Now find the start of the frame. */ | |||
| 2017 | ptr -= total_len; | |||
| 2018 | if (ptr < sc->dc_pnic_rx_buf) | |||
| 2019 | ptr = sc->dc_pnic_rx_buf; | |||
| 2020 | ||||
| 2021 | /* | |||
| 2022 | * Now copy the salvaged frame to the last mbuf and fake up | |||
| 2023 | * the status word to make it look like a successful | |||
| 2024 | * frame reception. | |||
| 2025 | */ | |||
| 2026 | dc_newbuf(sc, i, m); | |||
| 2027 | bcopy(ptr, mtod(m, char *)((char *)((m)->m_hdr.mh_data)), total_len); | |||
| 2028 | cur_rx->dc_status = htole32(rxstat | DC_RXSTAT_FIRSTFRAG)((__uint32_t)(rxstat | 0x00000200)); | |||
| 2029 | } | |||
| 2030 | ||||
| 2031 | /* | |||
| 2032 | * This routine searches the RX ring for dirty descriptors in the | |||
| 2033 | * event that the rxeof routine falls out of sync with the chip's | |||
| 2034 | * current descriptor pointer. This may happen sometimes as a result | |||
| 2035 | * of a "no RX buffer available" condition that happens when the chip | |||
| 2036 | * consumes all of the RX buffers before the driver has a chance to | |||
| 2037 | * process the RX ring. This routine may need to be called more than | |||
| 2038 | * once to bring the driver back in sync with the chip, however we | |||
| 2039 | * should still be getting RX DONE interrupts to drive the search | |||
| 2040 | * for new packets in the RX ring, so we should catch up eventually. | |||
| 2041 | */ | |||
| 2042 | int | |||
| 2043 | dc_rx_resync(struct dc_softc *sc) | |||
| 2044 | { | |||
| 2045 | u_int32_t stat; | |||
| 2046 | int i, pos, offset; | |||
| 2047 | ||||
| 2048 | pos = sc->dc_cdata.dc_rx_prod; | |||
| 2049 | ||||
| 2050 | for (i = 0; i < DC_RX_LIST_CNT64; i++) { | |||
| 2051 | ||||
| 2052 | offset = offsetof(struct dc_list_data, dc_rx_list[pos])__builtin_offsetof(struct dc_list_data, dc_rx_list[pos]); | |||
| 2053 | bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (offset), (sizeof(struct dc_desc)), (0x02 | 0x08 )) | |||
| 2054 | offset, sizeof(struct dc_desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (offset), (sizeof(struct dc_desc)), (0x02 | 0x08 )) | |||
| 2055 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (offset), (sizeof(struct dc_desc)), (0x02 | 0x08 )); | |||
| 2056 | ||||
| 2057 | stat = sc->dc_ldata->dc_rx_list[pos].dc_status; | |||
| 2058 | if (!(stat & htole32(DC_RXSTAT_OWN)((__uint32_t)(0x80000000)))) | |||
| 2059 | break; | |||
| 2060 | DC_INC(pos, DC_RX_LIST_CNT)(pos) = (pos + 1) % 64; | |||
| 2061 | } | |||
| 2062 | ||||
| 2063 | /* If the ring really is empty, then just return. */ | |||
| 2064 | if (i == DC_RX_LIST_CNT64) | |||
| 2065 | return (0); | |||
| 2066 | ||||
| 2067 | /* We've fallen behind the chip: catch it. */ | |||
| 2068 | sc->dc_cdata.dc_rx_prod = pos; | |||
| 2069 | ||||
| 2070 | return (EAGAIN35); | |||
| 2071 | } | |||
| 2072 | ||||
| 2073 | /* | |||
| 2074 | * A frame has been uploaded: pass the resulting mbuf chain up to | |||
| 2075 | * the higher level protocols. | |||
| 2076 | */ | |||
| 2077 | int | |||
| 2078 | dc_rxeof(struct dc_softc *sc) | |||
| 2079 | { | |||
| 2080 | struct mbuf *m; | |||
| 2081 | struct ifnet *ifp; | |||
| 2082 | struct dc_desc *cur_rx; | |||
| 2083 | struct mbuf_list ml = MBUF_LIST_INITIALIZER(){ ((void *)0), ((void *)0), 0 }; | |||
| 2084 | int i, offset, total_len = 0, consumed = 0; | |||
| 2085 | u_int32_t rxstat; | |||
| 2086 | ||||
| 2087 | ifp = &sc->sc_arpcom.ac_if; | |||
| 2088 | i = sc->dc_cdata.dc_rx_prod; | |||
| 2089 | ||||
| 2090 | for(;;) { | |||
| 2091 | struct mbuf *m0 = NULL((void *)0); | |||
| 2092 | ||||
| 2093 | offset = offsetof(struct dc_list_data, dc_rx_list[i])__builtin_offsetof(struct dc_list_data, dc_rx_list[i]); | |||
| 2094 | bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (offset), (sizeof(struct dc_desc)), (0x02 | 0x08 )) | |||
| 2095 | offset, sizeof(struct dc_desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (offset), (sizeof(struct dc_desc)), (0x02 | 0x08 )) | |||
| 2096 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (offset), (sizeof(struct dc_desc)), (0x02 | 0x08 )); | |||
| 2097 | ||||
| 2098 | cur_rx = &sc->dc_ldata->dc_rx_list[i]; | |||
| 2099 | rxstat = letoh32(cur_rx->dc_status)((__uint32_t)(cur_rx->dc_status)); | |||
| 2100 | if (rxstat & DC_RXSTAT_OWN0x80000000) | |||
| 2101 | break; | |||
| 2102 | ||||
| 2103 | m = sc->dc_cdata.dc_rx_chain[i].sd_mbuf; | |||
| 2104 | total_len = DC_RXBYTES(rxstat)((rxstat & 0x3FFF0000) >> 16); | |||
| 2105 | ||||
| 2106 | bus_dmamap_sync(sc->sc_dmat, sc->dc_cdata.dc_rx_chain[i].sd_map,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> dc_cdata.dc_rx_chain[i].sd_map), (0), (sc->dc_cdata.dc_rx_chain [i].sd_map->dm_mapsize), (0x02)) | |||
| 2107 | 0, sc->dc_cdata.dc_rx_chain[i].sd_map->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> dc_cdata.dc_rx_chain[i].sd_map), (0), (sc->dc_cdata.dc_rx_chain [i].sd_map->dm_mapsize), (0x02)) | |||
| 2108 | BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> dc_cdata.dc_rx_chain[i].sd_map), (0), (sc->dc_cdata.dc_rx_chain [i].sd_map->dm_mapsize), (0x02)); | |||
| 2109 | ||||
| 2110 | if (sc->dc_flags & DC_PNIC_RX_BUG_WAR0x00000040) { | |||
| 2111 | if ((rxstat & DC_WHOLEFRAME(0x00000200|0x00000100)) != DC_WHOLEFRAME(0x00000200|0x00000100)) { | |||
| 2112 | if (rxstat & DC_RXSTAT_FIRSTFRAG0x00000200) | |||
| 2113 | sc->dc_pnic_rx_bug_save = i; | |||
| 2114 | if ((rxstat & DC_RXSTAT_LASTFRAG0x00000100) == 0) { | |||
| 2115 | DC_INC(i, DC_RX_LIST_CNT)(i) = (i + 1) % 64; | |||
| 2116 | continue; | |||
| 2117 | } | |||
| 2118 | dc_pnic_rx_bug_war(sc, i); | |||
| 2119 | rxstat = letoh32(cur_rx->dc_status)((__uint32_t)(cur_rx->dc_status)); | |||
| 2120 | total_len = DC_RXBYTES(rxstat)((rxstat & 0x3FFF0000) >> 16); | |||
| 2121 | } | |||
| 2122 | } | |||
| 2123 | ||||
| 2124 | sc->dc_cdata.dc_rx_chain[i].sd_mbuf = NULL((void *)0); | |||
| 2125 | ||||
| 2126 | /* | |||
| 2127 | * If an error occurs, update stats, clear the | |||
| 2128 | * status word and leave the mbuf cluster in place: | |||
| 2129 | * it should simply get re-used next time this descriptor | |||
| 2130 | * comes up in the ring. However, don't report long | |||
| 2131 | * frames as errors since they could be VLANs. | |||
| 2132 | */ | |||
| 2133 | if ((rxstat & DC_RXSTAT_RXERR0x00008000)) { | |||
| 2134 | if (!(rxstat & DC_RXSTAT_GIANT0x00000080) || | |||
| 2135 | (rxstat & (DC_RXSTAT_CRCERR0x00000002 | DC_RXSTAT_DRIBBLE0x00000004 | | |||
| 2136 | DC_RXSTAT_MIIERE0x00000008 | DC_RXSTAT_COLLSEEN0x00000040 | | |||
| 2137 | DC_RXSTAT_RUNT0x00000800 | DC_RXSTAT_DE0x00004000))) { | |||
| 2138 | ifp->if_ierrorsif_data.ifi_ierrors++; | |||
| 2139 | if (rxstat & DC_RXSTAT_COLLSEEN0x00000040) | |||
| 2140 | ifp->if_collisionsif_data.ifi_collisions++; | |||
| 2141 | dc_newbuf(sc, i, m); | |||
| 2142 | if (rxstat & DC_RXSTAT_CRCERR0x00000002) { | |||
| 2143 | DC_INC(i, DC_RX_LIST_CNT)(i) = (i + 1) % 64; | |||
| 2144 | continue; | |||
| 2145 | } else { | |||
| 2146 | dc_init(sc); | |||
| 2147 | break; | |||
| 2148 | } | |||
| 2149 | } | |||
| 2150 | } | |||
| 2151 | ||||
| 2152 | /* No errors; receive the packet. */ | |||
| 2153 | total_len -= ETHER_CRC_LEN4; | |||
| 2154 | ||||
| 2155 | m0 = m_devget(mtod(m, char *)((char *)((m)->m_hdr.mh_data)), total_len, ETHER_ALIGN2); | |||
| 2156 | dc_newbuf(sc, i, m); | |||
| 2157 | DC_INC(i, DC_RX_LIST_CNT)(i) = (i + 1) % 64; | |||
| 2158 | if (m0 == NULL((void *)0)) { | |||
| 2159 | ifp->if_ierrorsif_data.ifi_ierrors++; | |||
| 2160 | continue; | |||
| 2161 | } | |||
| 2162 | m = m0; | |||
| 2163 | ||||
| 2164 | consumed++; | |||
| 2165 | ml_enqueue(&ml, m); | |||
| 2166 | } | |||
| 2167 | ||||
| 2168 | sc->dc_cdata.dc_rx_prod = i; | |||
| 2169 | ||||
| 2170 | if_input(ifp, &ml); | |||
| 2171 | ||||
| 2172 | return (consumed); | |||
| 2173 | } | |||
| 2174 | ||||
| 2175 | /* | |||
| 2176 | * A frame was downloaded to the chip. It's safe for us to clean up | |||
| 2177 | * the list buffers. | |||
| 2178 | */ | |||
| 2179 | ||||
| 2180 | void | |||
| 2181 | dc_txeof(struct dc_softc *sc) | |||
| 2182 | { | |||
| 2183 | struct dc_desc *cur_tx = NULL((void *)0); | |||
| 2184 | struct ifnet *ifp; | |||
| 2185 | int idx, offset; | |||
| 2186 | ||||
| 2187 | ifp = &sc->sc_arpcom.ac_if; | |||
| 2188 | ||||
| 2189 | /* | |||
| 2190 | * Go through our tx list and free mbufs for those | |||
| 2191 | * frames that have been transmitted. | |||
| 2192 | */ | |||
| 2193 | idx = sc->dc_cdata.dc_tx_cons; | |||
| 2194 | while(idx != sc->dc_cdata.dc_tx_prod) { | |||
| 2195 | u_int32_t txstat; | |||
| 2196 | ||||
| 2197 | offset = offsetof(struct dc_list_data, dc_tx_list[idx])__builtin_offsetof(struct dc_list_data, dc_tx_list[idx]); | |||
| 2198 | bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (offset), (sizeof(struct dc_desc)), (0x02 | 0x08 )) | |||
| 2199 | offset, sizeof(struct dc_desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (offset), (sizeof(struct dc_desc)), (0x02 | 0x08 )) | |||
| 2200 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (offset), (sizeof(struct dc_desc)), (0x02 | 0x08 )); | |||
| 2201 | ||||
| 2202 | cur_tx = &sc->dc_ldata->dc_tx_list[idx]; | |||
| 2203 | txstat = letoh32(cur_tx->dc_status)((__uint32_t)(cur_tx->dc_status)); | |||
| 2204 | ||||
| 2205 | if (txstat & DC_TXSTAT_OWN0x80000000) | |||
| 2206 | break; | |||
| 2207 | ||||
| 2208 | if (!(cur_tx->dc_ctl & htole32(DC_TXCTL_LASTFRAG)((__uint32_t)(0x40000000))) || | |||
| 2209 | cur_tx->dc_ctl & htole32(DC_TXCTL_SETUP)((__uint32_t)(0x08000000))) { | |||
| 2210 | if (cur_tx->dc_ctl & htole32(DC_TXCTL_SETUP)((__uint32_t)(0x08000000))) { | |||
| 2211 | /* | |||
| 2212 | * Yes, the PNIC is so brain damaged | |||
| 2213 | * that it will sometimes generate a TX | |||
| 2214 | * underrun error while DMAing the RX | |||
| 2215 | * filter setup frame. If we detect this, | |||
| 2216 | * we have to send the setup frame again, | |||
| 2217 | * or else the filter won't be programmed | |||
| 2218 | * correctly. | |||
| 2219 | */ | |||
| 2220 | if (DC_IS_PNIC(sc)(sc->dc_type == 0xA)) { | |||
| 2221 | if (txstat & DC_TXSTAT_ERRSUM0x00008000) | |||
| 2222 | dc_setfilt(sc); | |||
| 2223 | } | |||
| 2224 | sc->dc_cdata.dc_tx_chain[idx].sd_mbuf = NULL((void *)0); | |||
| 2225 | } | |||
| 2226 | sc->dc_cdata.dc_tx_cnt--; | |||
| 2227 | DC_INC(idx, DC_TX_LIST_CNT)(idx) = (idx + 1) % 256; | |||
| 2228 | continue; | |||
| 2229 | } | |||
| 2230 | ||||
| 2231 | if (DC_IS_XIRCOM(sc)(sc->dc_type == 0xB) || DC_IS_CONEXANT(sc)(sc->dc_type == 0xC)) { | |||
| 2232 | /* | |||
| 2233 | * XXX: Why does my Xircom taunt me so? | |||
| 2234 | * For some reason it likes setting the CARRLOST flag | |||
| 2235 | * even when the carrier is there. wtf?! | |||
| 2236 | * Who knows, but Conexant chips have the | |||
| 2237 | * same problem. Maybe they took lessons | |||
| 2238 | * from Xircom. | |||
| 2239 | */ | |||
| 2240 | if (/*sc->dc_type == DC_TYPE_21143 &&*/ | |||
| 2241 | sc->dc_pmode == DC_PMODE_MII0x1 && | |||
| 2242 | ((txstat & 0xFFFF) & ~(DC_TXSTAT_ERRSUM0x00008000| | |||
| 2243 | DC_TXSTAT_NOCARRIER0x00000400))) | |||
| 2244 | txstat &= ~DC_TXSTAT_ERRSUM0x00008000; | |||
| 2245 | } else { | |||
| 2246 | if (/*sc->dc_type == DC_TYPE_21143 &&*/ | |||
| 2247 | sc->dc_pmode == DC_PMODE_MII0x1 && | |||
| 2248 | ((txstat & 0xFFFF) & ~(DC_TXSTAT_ERRSUM0x00008000| | |||
| 2249 | DC_TXSTAT_NOCARRIER0x00000400|DC_TXSTAT_CARRLOST0x00000800))) | |||
| 2250 | txstat &= ~DC_TXSTAT_ERRSUM0x00008000; | |||
| 2251 | } | |||
| 2252 | ||||
| 2253 | if (txstat & DC_TXSTAT_ERRSUM0x00008000) { | |||
| 2254 | ifp->if_oerrorsif_data.ifi_oerrors++; | |||
| 2255 | if (txstat & DC_TXSTAT_EXCESSCOLL0x00000100) | |||
| 2256 | ifp->if_collisionsif_data.ifi_collisions++; | |||
| 2257 | if (txstat & DC_TXSTAT_LATECOLL0x00000200) | |||
| 2258 | ifp->if_collisionsif_data.ifi_collisions++; | |||
| 2259 | if (!(txstat & DC_TXSTAT_UNDERRUN0x00000002)) { | |||
| 2260 | dc_init(sc); | |||
| 2261 | return; | |||
| 2262 | } | |||
| 2263 | } | |||
| 2264 | ||||
| 2265 | ifp->if_collisionsif_data.ifi_collisions += (txstat & DC_TXSTAT_COLLCNT0x00000078) >> 3; | |||
| 2266 | ||||
| 2267 | if (sc->dc_cdata.dc_tx_chain[idx].sd_map->dm_nsegs != 0) { | |||
| 2268 | bus_dmamap_t map = sc->dc_cdata.dc_tx_chain[idx].sd_map; | |||
| 2269 | ||||
| 2270 | bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (map), (0), (map->dm_mapsize), (0x08)) | |||
| 2271 | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (map), (0), (map->dm_mapsize), (0x08)); | |||
| 2272 | bus_dmamap_unload(sc->sc_dmat, map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (map )); | |||
| 2273 | } | |||
| 2274 | if (sc->dc_cdata.dc_tx_chain[idx].sd_mbuf != NULL((void *)0)) { | |||
| 2275 | m_freem(sc->dc_cdata.dc_tx_chain[idx].sd_mbuf); | |||
| 2276 | sc->dc_cdata.dc_tx_chain[idx].sd_mbuf = NULL((void *)0); | |||
| 2277 | } | |||
| 2278 | ||||
| 2279 | bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (offset), (sizeof(struct dc_desc)), (0x02 | 0x08 )) | |||
| 2280 | offset, sizeof(struct dc_desc),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (offset), (sizeof(struct dc_desc)), (0x02 | 0x08 )) | |||
| 2281 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (offset), (sizeof(struct dc_desc)), (0x02 | 0x08 )); | |||
| 2282 | ||||
| 2283 | sc->dc_cdata.dc_tx_cnt--; | |||
| 2284 | DC_INC(idx, DC_TX_LIST_CNT)(idx) = (idx + 1) % 256; | |||
| 2285 | } | |||
| 2286 | sc->dc_cdata.dc_tx_cons = idx; | |||
| 2287 | ||||
| 2288 | if (DC_TX_LIST_CNT256 - sc->dc_cdata.dc_tx_cnt > 5) | |||
| 2289 | ifq_clr_oactive(&ifp->if_snd); | |||
| 2290 | if (sc->dc_cdata.dc_tx_cnt == 0) | |||
| 2291 | ifp->if_timer = 0; | |||
| 2292 | } | |||
| 2293 | ||||
| 2294 | void | |||
| 2295 | dc_tick(void *xsc) | |||
| 2296 | { | |||
| 2297 | struct dc_softc *sc = (struct dc_softc *)xsc; | |||
| 2298 | struct mii_data *mii; | |||
| 2299 | struct ifnet *ifp; | |||
| 2300 | int s; | |||
| 2301 | u_int32_t r; | |||
| 2302 | ||||
| 2303 | s = splnet()splraise(0x7); | |||
| 2304 | ||||
| 2305 | ifp = &sc->sc_arpcom.ac_if; | |||
| 2306 | mii = &sc->sc_mii; | |||
| 2307 | ||||
| 2308 | if (sc->dc_flags & DC_REDUCED_MII_POLL0x00000200) { | |||
| 2309 | if (sc->dc_flags & DC_21143_NWAY0x00000800) { | |||
| 2310 | r = CSR_READ_4(sc, DC_10BTSTAT)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x60))); | |||
| 2311 | if (IFM_SUBTYPE(mii->mii_media_active)((mii->mii_media_active) & 0x00000000000000ffULL) == | |||
| 2312 | IFM_100_TX6 && (r & DC_TSTAT_LS1000x00000002)) { | |||
| 2313 | sc->dc_link = 0; | |||
| 2314 | mii_mediachg(mii); | |||
| 2315 | } | |||
| 2316 | if (IFM_SUBTYPE(mii->mii_media_active)((mii->mii_media_active) & 0x00000000000000ffULL) == | |||
| 2317 | IFM_10_T3 && (r & DC_TSTAT_LS100x00000004)) { | |||
| 2318 | sc->dc_link = 0; | |||
| 2319 | mii_mediachg(mii); | |||
| 2320 | } | |||
| 2321 | if (sc->dc_link == 0) | |||
| 2322 | mii_tick(mii); | |||
| 2323 | } else { | |||
| 2324 | /* | |||
| 2325 | * For NICs which never report DC_RXSTATE_WAIT, we | |||
| 2326 | * have to bite the bullet... | |||
| 2327 | */ | |||
| 2328 | if ((DC_HAS_BROKEN_RXSTATE(sc)((sc->dc_type == 0x7) || (sc->dc_type == 0xC) || ((sc-> dc_type == 0x8) && sc->dc_revision >= 0x30)) || (CSR_READ_4(sc,((sc->dc_btag)->read_4((sc->dc_bhandle), (0x28))) | |||
| 2329 | DC_ISR)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x28))) & DC_ISR_RX_STATE0x000E0000) == DC_RXSTATE_WAIT0x00060000) && | |||
| 2330 | sc->dc_cdata.dc_tx_cnt == 0 && !DC_IS_ASIX(sc)(sc->dc_type == 0x5)) { | |||
| 2331 | mii_tick(mii); | |||
| 2332 | if (!(mii->mii_media_status & IFM_ACTIVE0x0000000000000002ULL)) | |||
| 2333 | sc->dc_link = 0; | |||
| 2334 | } | |||
| 2335 | } | |||
| 2336 | } else | |||
| 2337 | mii_tick(mii); | |||
| 2338 | ||||
| 2339 | /* | |||
| 2340 | * When the init routine completes, we expect to be able to send | |||
| 2341 | * packets right away, and in fact the network code will send a | |||
| 2342 | * gratuitous ARP the moment the init routine marks the interface | |||
| 2343 | * as running. However, even though the MAC may have been initialized, | |||
| 2344 | * there may be a delay of a few seconds before the PHY completes | |||
| 2345 | * autonegotiation and the link is brought up. Any transmissions | |||
| 2346 | * made during that delay will be lost. Dealing with this is tricky: | |||
| 2347 | * we can't just pause in the init routine while waiting for the | |||
| 2348 | * PHY to come ready since that would bring the whole system to | |||
| 2349 | * a screeching halt for several seconds. | |||
| 2350 | * | |||
| 2351 | * What we do here is prevent the TX start routine from sending | |||
| 2352 | * any packets until a link has been established. After the | |||
| 2353 | * interface has been initialized, the tick routine will poll | |||
| 2354 | * the state of the PHY until the IFM_ACTIVE flag is set. Until | |||
| 2355 | * that time, packets will stay in the send queue, and once the | |||
| 2356 | * link comes up, they will be flushed out to the wire. | |||
| 2357 | */ | |||
| 2358 | if (!sc->dc_link && mii->mii_media_status & IFM_ACTIVE0x0000000000000002ULL && | |||
| 2359 | IFM_SUBTYPE(mii->mii_media_active)((mii->mii_media_active) & 0x00000000000000ffULL) != IFM_NONE2ULL) { | |||
| 2360 | sc->dc_link++; | |||
| 2361 | if (ifq_empty(&ifp->if_snd)(((&ifp->if_snd)->ifq_len) == 0) == 0) | |||
| 2362 | dc_start(ifp); | |||
| 2363 | } | |||
| 2364 | ||||
| 2365 | if (sc->dc_flags & DC_21143_NWAY0x00000800 && !sc->dc_link) | |||
| 2366 | timeout_add_msec(&sc->dc_tick_tmo, 100); | |||
| 2367 | else | |||
| 2368 | timeout_add_sec(&sc->dc_tick_tmo, 1); | |||
| 2369 | ||||
| 2370 | splx(s)spllower(s); | |||
| 2371 | } | |||
| 2372 | ||||
| 2373 | /* A transmit underrun has occurred. Back off the transmit threshold, | |||
| 2374 | * or switch to store and forward mode if we have to. | |||
| 2375 | */ | |||
| 2376 | void | |||
| 2377 | dc_tx_underrun(struct dc_softc *sc) | |||
| 2378 | { | |||
| 2379 | u_int32_t isr; | |||
| 2380 | int i; | |||
| 2381 | ||||
| 2382 | if (DC_IS_DAVICOM(sc)(sc->dc_type == 0x8)) | |||
| 2383 | dc_init(sc); | |||
| 2384 | ||||
| 2385 | if (DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD)) { | |||
| 2386 | /* | |||
| 2387 | * The real 21143 requires that the transmitter be idle | |||
| 2388 | * in order to change the transmit threshold or store | |||
| 2389 | * and forward state. | |||
| 2390 | */ | |||
| 2391 | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~(0x00002000)))); | |||
| 2392 | ||||
| 2393 | for (i = 0; i < DC_TIMEOUT1000; i++) { | |||
| 2394 | isr = CSR_READ_4(sc, DC_ISR)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x28))); | |||
| 2395 | if (isr & DC_ISR_TX_IDLE0x00000002) | |||
| 2396 | break; | |||
| 2397 | DELAY(10)(*delay_func)(10); | |||
| 2398 | } | |||
| 2399 | if (i == DC_TIMEOUT1000) { | |||
| 2400 | printf("%s: failed to force tx to idle state\n", | |||
| 2401 | sc->sc_dev.dv_xname); | |||
| 2402 | dc_init(sc); | |||
| 2403 | } | |||
| 2404 | } | |||
| 2405 | ||||
| 2406 | sc->dc_txthresh += DC_TXTHRESH_INC0x00004000; | |||
| 2407 | if (sc->dc_txthresh > DC_TXTHRESH_MAX0x0000C000) { | |||
| 2408 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00200000)))); | |||
| 2409 | } else { | |||
| 2410 | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~(0x0000C000)))); | |||
| 2411 | DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( sc->dc_txthresh)))); | |||
| 2412 | } | |||
| 2413 | ||||
| 2414 | if (DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD)) | |||
| 2415 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00002000)))); | |||
| 2416 | ||||
| 2417 | return; | |||
| 2418 | } | |||
| 2419 | ||||
| 2420 | int | |||
| 2421 | dc_intr(void *arg) | |||
| 2422 | { | |||
| 2423 | struct dc_softc *sc; | |||
| 2424 | struct ifnet *ifp; | |||
| 2425 | u_int32_t status, ints; | |||
| 2426 | int claimed = 0; | |||
| 2427 | ||||
| 2428 | sc = arg; | |||
| 2429 | ||||
| 2430 | ifp = &sc->sc_arpcom.ac_if; | |||
| 2431 | ||||
| 2432 | ints = CSR_READ_4(sc, DC_ISR)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x28))); | |||
| 2433 | if ((ints & DC_INTRS(0x00000040|0x00000001|0x00000080|0x00000200| 0x00000002|0x00000004 |0x00000020|0x00002000| 0x00008000|0x00010000 )) == 0) | |||
| 2434 | return (claimed); | |||
| 2435 | if (ints == 0xffffffff) | |||
| 2436 | return (0); | |||
| 2437 | ||||
| 2438 | /* Suppress unwanted interrupts */ | |||
| 2439 | if (!(ifp->if_flags & IFF_UP0x1)) { | |||
| 2440 | if (CSR_READ_4(sc, DC_ISR)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x28))) & DC_INTRS(0x00000040|0x00000001|0x00000080|0x00000200| 0x00000002|0x00000004 |0x00000020|0x00002000| 0x00008000|0x00010000 )) | |||
| 2441 | dc_stop(sc, 0); | |||
| 2442 | return (claimed); | |||
| 2443 | } | |||
| 2444 | ||||
| 2445 | /* Disable interrupts. */ | |||
| 2446 | CSR_WRITE_4(sc, DC_IMR, 0x00000000)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x38), (0x00000000 ))); | |||
| 2447 | ||||
| 2448 | while (((status = CSR_READ_4(sc, DC_ISR)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x28)))) & DC_INTRS(0x00000040|0x00000001|0x00000080|0x00000200| 0x00000002|0x00000004 |0x00000020|0x00002000| 0x00008000|0x00010000 )) && | |||
| 2449 | status != 0xFFFFFFFF && | |||
| 2450 | (ifp->if_flags & IFF_RUNNING0x40)) { | |||
| 2451 | ||||
| 2452 | claimed = 1; | |||
| 2453 | CSR_WRITE_4(sc, DC_ISR, status)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x28), (status ))); | |||
| 2454 | ||||
| 2455 | if (status & DC_ISR_RX_OK0x00000040) { | |||
| 2456 | if (dc_rxeof(sc) == 0) { | |||
| 2457 | while(dc_rx_resync(sc)) | |||
| 2458 | dc_rxeof(sc); | |||
| 2459 | } | |||
| 2460 | } | |||
| 2461 | ||||
| 2462 | if (status & (DC_ISR_TX_OK0x00000001|DC_ISR_TX_NOBUF0x00000004)) | |||
| 2463 | dc_txeof(sc); | |||
| 2464 | ||||
| 2465 | if (status & DC_ISR_TX_IDLE0x00000002) { | |||
| 2466 | dc_txeof(sc); | |||
| 2467 | if (sc->dc_cdata.dc_tx_cnt) { | |||
| 2468 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00002000)))); | |||
| 2469 | CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x08), (0xFFFFFFFF ))); | |||
| 2470 | } | |||
| 2471 | } | |||
| 2472 | ||||
| 2473 | if (status & DC_ISR_TX_UNDERRUN0x00000020) | |||
| 2474 | dc_tx_underrun(sc); | |||
| 2475 | ||||
| 2476 | if ((status & DC_ISR_RX_WATDOGTIMEO0x00000200) | |||
| 2477 | || (status & DC_ISR_RX_NOBUF0x00000080)) { | |||
| 2478 | if (dc_rxeof(sc) == 0) { | |||
| 2479 | while(dc_rx_resync(sc)) | |||
| 2480 | dc_rxeof(sc); | |||
| 2481 | } | |||
| 2482 | } | |||
| 2483 | ||||
| 2484 | if (status & DC_ISR_BUS_ERR0x00002000) | |||
| 2485 | dc_init(sc); | |||
| 2486 | } | |||
| 2487 | ||||
| 2488 | /* Re-enable interrupts. */ | |||
| 2489 | CSR_WRITE_4(sc, DC_IMR, DC_INTRS)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x38), (( 0x00000040|0x00000001|0x00000080|0x00000200| 0x00000002|0x00000004 |0x00000020|0x00002000| 0x00008000|0x00010000 )))); | |||
| 2490 | ||||
| 2491 | if (ifq_empty(&ifp->if_snd)(((&ifp->if_snd)->ifq_len) == 0) == 0) | |||
| 2492 | dc_start(ifp); | |||
| 2493 | ||||
| 2494 | return (claimed); | |||
| 2495 | } | |||
| 2496 | ||||
| 2497 | /* | |||
| 2498 | * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data | |||
| 2499 | * pointers to the fragment pointers. | |||
| 2500 | */ | |||
| 2501 | int | |||
| 2502 | dc_encap(struct dc_softc *sc, bus_dmamap_t map, struct mbuf *m, u_int32_t *idx) | |||
| 2503 | { | |||
| 2504 | struct dc_desc *f = NULL((void *)0); | |||
| 2505 | int frag, cur, cnt = 0, i; | |||
| 2506 | ||||
| 2507 | cur = frag = *idx; | |||
| 2508 | ||||
| 2509 | for (i = 0; i < map->dm_nsegs; i++) { | |||
| 2510 | f = &sc->dc_ldata->dc_tx_list[frag]; | |||
| 2511 | f->dc_ctl = htole32(DC_TXCTL_TLINK | map->dm_segs[i].ds_len)((__uint32_t)(0x01000000 | map->dm_segs[i].ds_len)); | |||
| 2512 | if (cnt == 0) { | |||
| 2513 | f->dc_status = htole32(0)((__uint32_t)(0)); | |||
| 2514 | f->dc_ctl |= htole32(DC_TXCTL_FIRSTFRAG)((__uint32_t)(0x20000000)); | |||
| 2515 | } else | |||
| 2516 | f->dc_status = htole32(DC_TXSTAT_OWN)((__uint32_t)(0x80000000)); | |||
| 2517 | f->dc_datadc_ptr1 = htole32(map->dm_segs[i].ds_addr)((__uint32_t)(map->dm_segs[i].ds_addr)); | |||
| 2518 | cur = frag; | |||
| 2519 | DC_INC(frag, DC_TX_LIST_CNT)(frag) = (frag + 1) % 256; | |||
| 2520 | cnt++; | |||
| 2521 | } | |||
| 2522 | ||||
| 2523 | sc->dc_cdata.dc_tx_cnt += cnt; | |||
| 2524 | sc->dc_cdata.dc_tx_chain[cur].sd_mbuf = m; | |||
| 2525 | sc->sc_tx_sparemap = sc->dc_cdata.dc_tx_chain[cur].sd_map; | |||
| 2526 | sc->dc_cdata.dc_tx_chain[cur].sd_map = map; | |||
| 2527 | sc->dc_ldata->dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_LASTFRAG)((__uint32_t)(0x40000000)); | |||
| 2528 | if (sc->dc_flags & DC_TX_INTR_FIRSTFRAG0x00000020) | |||
| 2529 | sc->dc_ldata->dc_tx_list[*idx].dc_ctl |= | |||
| 2530 | htole32(DC_TXCTL_FINT)((__uint32_t)(0x80000000)); | |||
| 2531 | if (sc->dc_flags & DC_TX_INTR_ALWAYS0x00000400) | |||
| 2532 | sc->dc_ldata->dc_tx_list[cur].dc_ctl |= | |||
| 2533 | htole32(DC_TXCTL_FINT)((__uint32_t)(0x80000000)); | |||
| 2534 | if (sc->dc_flags & DC_TX_USE_TX_INTR0x00000008 && sc->dc_cdata.dc_tx_cnt > 64) | |||
| 2535 | sc->dc_ldata->dc_tx_list[cur].dc_ctl |= | |||
| 2536 | htole32(DC_TXCTL_FINT)((__uint32_t)(0x80000000)); | |||
| 2537 | bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (map), (0), (map->dm_mapsize), (0x04)) | |||
| 2538 | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (map), (0), (map->dm_mapsize), (0x04)); | |||
| 2539 | ||||
| 2540 | sc->dc_ldata->dc_tx_list[*idx].dc_status = htole32(DC_TXSTAT_OWN)((__uint32_t)(0x80000000)); | |||
| 2541 | ||||
| 2542 | *idx = frag; | |||
| 2543 | ||||
| 2544 | return (0); | |||
| 2545 | } | |||
| 2546 | ||||
| 2547 | /* | |||
| 2548 | * Main transmit routine. To avoid having to do mbuf copies, we put pointers | |||
| 2549 | * to the mbuf data regions directly in the transmit lists. We also save a | |||
| 2550 | * copy of the pointers since the transmit list fragment pointers are | |||
| 2551 | * physical addresses. | |||
| 2552 | */ | |||
| 2553 | ||||
| 2554 | static inline int | |||
| 2555 | dc_fits(struct dc_softc *sc, int idx, bus_dmamap_t map) | |||
| 2556 | { | |||
| 2557 | if (sc->dc_flags & DC_TX_ADMTEK_WAR0x00000004) { | |||
| 2558 | if (sc->dc_cdata.dc_tx_prod != idx && | |||
| 2559 | idx + map->dm_nsegs >= DC_TX_LIST_CNT256) | |||
| 2560 | return (0); | |||
| 2561 | } | |||
| 2562 | ||||
| 2563 | if (sc->dc_cdata.dc_tx_cnt + map->dm_nsegs + 5 > DC_TX_LIST_CNT256) | |||
| 2564 | return (0); | |||
| 2565 | ||||
| 2566 | return (1); | |||
| 2567 | } | |||
| 2568 | ||||
| 2569 | void | |||
| 2570 | dc_start(struct ifnet *ifp) | |||
| 2571 | { | |||
| 2572 | struct dc_softc *sc = ifp->if_softc; | |||
| 2573 | bus_dmamap_t map; | |||
| 2574 | struct mbuf *m; | |||
| 2575 | int idx; | |||
| 2576 | ||||
| 2577 | if (!sc->dc_link && ifq_len(&ifp->if_snd)((&ifp->if_snd)->ifq_len) < 10) | |||
| 2578 | return; | |||
| 2579 | ||||
| 2580 | if (ifq_is_oactive(&ifp->if_snd)) | |||
| 2581 | return; | |||
| 2582 | ||||
| 2583 | idx = sc->dc_cdata.dc_tx_prod; | |||
| 2584 | ||||
| 2585 | bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_tx_list )), (sizeof(struct dc_desc) * 256), (0x02 | 0x08)) | |||
| 2586 | offsetof(struct dc_list_data, dc_tx_list),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_tx_list )), (sizeof(struct dc_desc) * 256), (0x02 | 0x08)) | |||
| 2587 | sizeof(struct dc_desc) * DC_TX_LIST_CNT,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_tx_list )), (sizeof(struct dc_desc) * 256), (0x02 | 0x08)) | |||
| 2588 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_tx_list )), (sizeof(struct dc_desc) * 256), (0x02 | 0x08)); | |||
| 2589 | ||||
| 2590 | for (;;) { | |||
| 2591 | m = ifq_deq_begin(&ifp->if_snd); | |||
| 2592 | if (m == NULL((void *)0)) | |||
| 2593 | break; | |||
| 2594 | ||||
| 2595 | map = sc->sc_tx_sparemap; | |||
| 2596 | switch (bus_dmamap_load_mbuf(sc->sc_dmat, map, m,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( map), (m), (0x0001 | 0)) | |||
| 2597 | BUS_DMA_NOWAIT | BUS_DMA_OVERRUN)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( map), (m), (0x0001 | 0))) { | |||
| 2598 | case 0: | |||
| 2599 | break; | |||
| 2600 | case EFBIG27: | |||
| 2601 | if (m_defrag(m, M_DONTWAIT0x0002) == 0 && | |||
| 2602 | bus_dmamap_load_mbuf(sc->sc_dmat, map, m,(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( map), (m), (0x0001 | 0)) | |||
| 2603 | BUS_DMA_NOWAIT | BUS_DMA_OVERRUN)(*(sc->sc_dmat)->_dmamap_load_mbuf)((sc->sc_dmat), ( map), (m), (0x0001 | 0)) == 0) | |||
| 2604 | break; | |||
| 2605 | ||||
| 2606 | /* FALLTHROUGH */ | |||
| 2607 | default: | |||
| 2608 | ifq_deq_commit(&ifp->if_snd, m); | |||
| 2609 | m_freem(m); | |||
| 2610 | ifp->if_oerrorsif_data.ifi_oerrors++; | |||
| 2611 | continue; | |||
| 2612 | } | |||
| 2613 | ||||
| 2614 | if (!dc_fits(sc, idx, map)) { | |||
| 2615 | bus_dmamap_unload(sc->sc_dmat, map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (map )); | |||
| 2616 | ifq_deq_rollback(&ifp->if_snd, m); | |||
| 2617 | ifq_set_oactive(&ifp->if_snd); | |||
| 2618 | break; | |||
| 2619 | } | |||
| 2620 | ||||
| 2621 | /* now we are committed to transmit the packet */ | |||
| 2622 | ifq_deq_commit(&ifp->if_snd, m); | |||
| 2623 | ||||
| 2624 | if (dc_encap(sc, map, m, &idx) != 0) { | |||
| 2625 | m_freem(m); | |||
| 2626 | ifp->if_oerrorsif_data.ifi_oerrors++; | |||
| 2627 | continue; | |||
| 2628 | } | |||
| 2629 | ||||
| 2630 | /* | |||
| 2631 | * If there's a BPF listener, bounce a copy of this frame | |||
| 2632 | * to him. | |||
| 2633 | */ | |||
| 2634 | #if NBPFILTER1 > 0 | |||
| 2635 | if (ifp->if_bpf) | |||
| 2636 | bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT(1 << 1)); | |||
| 2637 | #endif | |||
| 2638 | ||||
| 2639 | if (sc->dc_flags & DC_TX_ONE0x00008000) { | |||
| 2640 | ifq_set_oactive(&ifp->if_snd); | |||
| 2641 | break; | |||
| 2642 | } | |||
| 2643 | } | |||
| 2644 | ||||
| 2645 | bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_tx_list )), (sizeof(struct dc_desc) * 256), (0x01 | 0x04)) | |||
| 2646 | offsetof(struct dc_list_data, dc_tx_list),(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_tx_list )), (sizeof(struct dc_desc) * 256), (0x01 | 0x04)) | |||
| 2647 | sizeof(struct dc_desc) * DC_TX_LIST_CNT,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_tx_list )), (sizeof(struct dc_desc) * 256), (0x01 | 0x04)) | |||
| 2648 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (__builtin_offsetof(struct dc_list_data, dc_tx_list )), (sizeof(struct dc_desc) * 256), (0x01 | 0x04)); | |||
| 2649 | ||||
| 2650 | if (idx == sc->dc_cdata.dc_tx_prod) | |||
| 2651 | return; | |||
| 2652 | ||||
| 2653 | /* Transmit */ | |||
| 2654 | sc->dc_cdata.dc_tx_prod = idx; | |||
| 2655 | if (!(sc->dc_flags & DC_TX_POLL0x00000001)) | |||
| 2656 | CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x08), (0xFFFFFFFF ))); | |||
| 2657 | ||||
| 2658 | /* | |||
| 2659 | * Set a timeout in case the chip goes out to lunch. | |||
| 2660 | */ | |||
| 2661 | ifp->if_timer = 5; | |||
| 2662 | } | |||
| 2663 | ||||
| 2664 | void | |||
| 2665 | dc_init(void *xsc) | |||
| 2666 | { | |||
| 2667 | struct dc_softc *sc = xsc; | |||
| 2668 | struct ifnet *ifp = &sc->sc_arpcom.ac_if; | |||
| 2669 | struct mii_data *mii; | |||
| 2670 | int s; | |||
| 2671 | ||||
| 2672 | s = splnet()splraise(0x7); | |||
| 2673 | ||||
| 2674 | mii = &sc->sc_mii; | |||
| 2675 | ||||
| 2676 | /* | |||
| 2677 | * Cancel pending I/O and free all RX/TX buffers. | |||
| 2678 | */ | |||
| 2679 | dc_stop(sc, 0); | |||
| 2680 | dc_reset(sc); | |||
| 2681 | ||||
| 2682 | /* | |||
| 2683 | * Set cache alignment and burst length. | |||
| 2684 | */ | |||
| 2685 | if (DC_IS_ASIX(sc)(sc->dc_type == 0x5) || DC_IS_DAVICOM(sc)(sc->dc_type == 0x8)) | |||
| 2686 | CSR_WRITE_4(sc, DC_BUSCTL, 0)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x00), (0 ))); | |||
| 2687 | else | |||
| 2688 | CSR_WRITE_4(sc, DC_BUSCTL, DC_BUSCTL_MRME|DC_BUSCTL_MRLE)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x00), (0x00200000 |0x00800000))); | |||
| 2689 | /* | |||
| 2690 | * Evenly share the bus between receive and transmit process. | |||
| 2691 | */ | |||
| 2692 | if (DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD)) | |||
| 2693 | DC_SETBIT(sc, DC_BUSCTL, DC_BUSCTL_ARBITRATION)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x00), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x00))) | ( 0x00000002)))); | |||
| 2694 | if (DC_IS_DAVICOM(sc)(sc->dc_type == 0x8) || DC_IS_INTEL(sc)(sc->dc_type == 0x4 || sc->dc_type == 0xD)) { | |||
| 2695 | DC_SETBIT(sc, DC_BUSCTL, DC_BURSTLEN_USECA)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x00), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x00))) | ( 0x00000000)))); | |||
| 2696 | } else { | |||
| 2697 | DC_SETBIT(sc, DC_BUSCTL, DC_BURSTLEN_16LONG)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x00), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x00))) | ( 0x00001000)))); | |||
| 2698 | } | |||
| 2699 | if (sc->dc_flags & DC_TX_POLL0x00000001) | |||
| 2700 | DC_SETBIT(sc, DC_BUSCTL, DC_TXPOLL_1)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x00), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x00))) | ( 0x00020000)))); | |||
| 2701 | switch(sc->dc_cachesize) { | |||
| 2702 | case 32: | |||
| 2703 | DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_32LONG)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x00), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x00))) | ( 0x0000C000)))); | |||
| 2704 | break; | |||
| 2705 | case 16: | |||
| 2706 | DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_16LONG)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x00), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x00))) | ( 0x00008000)))); | |||
| 2707 | break; | |||
| 2708 | case 8: | |||
| 2709 | DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_8LONG)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x00), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x00))) | ( 0x00004000)))); | |||
| 2710 | break; | |||
| 2711 | case 0: | |||
| 2712 | default: | |||
| 2713 | DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_NONE)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x00), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x00))) | ( 0x00000000)))); | |||
| 2714 | break; | |||
| 2715 | } | |||
| 2716 | ||||
| 2717 | if (sc->dc_flags & DC_TX_STORENFWD0x00000100) | |||
| 2718 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00200000)))); | |||
| 2719 | else { | |||
| 2720 | if (sc->dc_txthresh > DC_TXTHRESH_MAX0x0000C000) { | |||
| 2721 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00200000)))); | |||
| 2722 | } else { | |||
| 2723 | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~(0x00200000)))); | |||
| 2724 | DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( sc->dc_txthresh)))); | |||
| 2725 | } | |||
| 2726 | } | |||
| 2727 | ||||
| 2728 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_NO_RXCRC)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x02000000)))); | |||
| 2729 | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_BACKOFF)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~(0x00020000)))); | |||
| 2730 | ||||
| 2731 | if (DC_IS_MACRONIX(sc)(sc->dc_type == 0x1 || sc->dc_type == 0x2 || sc->dc_type == 0x3) || DC_IS_PNICII(sc)(sc->dc_type == 0x9)) { | |||
| 2732 | /* | |||
| 2733 | * The app notes for the 98713 and 98715A say that | |||
| 2734 | * in order to have the chips operate properly, a magic | |||
| 2735 | * number must be written to CSR16. Macronix does not | |||
| 2736 | * document the meaning of these bits so there's no way | |||
| 2737 | * to know exactly what they do. The 98713 has a magic | |||
| 2738 | * number all its own; the rest all use a different one. | |||
| 2739 | */ | |||
| 2740 | DC_CLRBIT(sc, DC_MX_MAGICPACKET, 0xFFFF0000)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x80), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x80))) & ~(0xFFFF0000)))); | |||
| 2741 | if (sc->dc_type == DC_TYPE_987130x1) | |||
| 2742 | DC_SETBIT(sc, DC_MX_MAGICPACKET, DC_MX_MAGIC_98713)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x80), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x80))) | ( 0x0F370000)))); | |||
| 2743 | else | |||
| 2744 | DC_SETBIT(sc, DC_MX_MAGICPACKET, DC_MX_MAGIC_98715)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x80), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x80))) | ( 0x0B3C0000)))); | |||
| 2745 | } | |||
| 2746 | ||||
| 2747 | if (DC_IS_XIRCOM(sc)(sc->dc_type == 0xB)) { | |||
| 2748 | CSR_WRITE_4(sc, DC_SIAGP, DC_SIAGP_WRITE_EN | DC_SIAGP_INT1_EN |((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (0x08000000 | 0x02000000 | 0x00040000 | 0x00010000))) | |||
| 2749 | DC_SIAGP_MD_GP2_OUTPUT | DC_SIAGP_MD_GP0_OUTPUT)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (0x08000000 | 0x02000000 | 0x00040000 | 0x00010000))); | |||
| 2750 | DELAY(10)(*delay_func)(10); | |||
| 2751 | CSR_WRITE_4(sc, DC_SIAGP, DC_SIAGP_INT1_EN |((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (0x02000000 | 0x00040000 | 0x00010000))) | |||
| 2752 | DC_SIAGP_MD_GP2_OUTPUT | DC_SIAGP_MD_GP0_OUTPUT)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (0x02000000 | 0x00040000 | 0x00010000))); | |||
| 2753 | DELAY(10)(*delay_func)(10); | |||
| 2754 | } | |||
| 2755 | ||||
| 2756 | DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~(0x0000C000)))); | |||
| 2757 | DC_SETBIT(sc, DC_NETCFG, DC_TXTHRESH_MIN)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00000000)))); | |||
| 2758 | ||||
| 2759 | /* Init circular RX list. */ | |||
| 2760 | if (dc_list_rx_init(sc) == ENOBUFS55) { | |||
| 2761 | printf("%s: initialization failed: no " | |||
| 2762 | "memory for rx buffers\n", sc->sc_dev.dv_xname); | |||
| 2763 | dc_stop(sc, 0); | |||
| 2764 | splx(s)spllower(s); | |||
| 2765 | return; | |||
| 2766 | } | |||
| 2767 | ||||
| 2768 | /* | |||
| 2769 | * Init tx descriptors. | |||
| 2770 | */ | |||
| 2771 | dc_list_tx_init(sc); | |||
| 2772 | ||||
| 2773 | /* | |||
| 2774 | * Sync down both lists initialized. | |||
| 2775 | */ | |||
| 2776 | bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (0), (sc->sc_listmap->dm_mapsize), (0x01 | 0x04)) | |||
| 2777 | 0, sc->sc_listmap->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (0), (sc->sc_listmap->dm_mapsize), (0x01 | 0x04)) | |||
| 2778 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (0), (sc->sc_listmap->dm_mapsize), (0x01 | 0x04)); | |||
| 2779 | ||||
| 2780 | /* | |||
| 2781 | * Load the address of the RX list. | |||
| 2782 | */ | |||
| 2783 | CSR_WRITE_4(sc, DC_RXADDR, sc->sc_listmap->dm_segs[0].ds_addr +((sc->dc_btag)->write_4((sc->dc_bhandle), (0x18), (sc ->sc_listmap->dm_segs[0].ds_addr + __builtin_offsetof(struct dc_list_data, dc_rx_list[0])))) | |||
| 2784 | offsetof(struct dc_list_data, dc_rx_list[0]))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x18), (sc ->sc_listmap->dm_segs[0].ds_addr + __builtin_offsetof(struct dc_list_data, dc_rx_list[0])))); | |||
| 2785 | CSR_WRITE_4(sc, DC_TXADDR, sc->sc_listmap->dm_segs[0].ds_addr +((sc->dc_btag)->write_4((sc->dc_bhandle), (0x20), (sc ->sc_listmap->dm_segs[0].ds_addr + __builtin_offsetof(struct dc_list_data, dc_tx_list[0])))) | |||
| 2786 | offsetof(struct dc_list_data, dc_tx_list[0]))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x20), (sc ->sc_listmap->dm_segs[0].ds_addr + __builtin_offsetof(struct dc_list_data, dc_tx_list[0])))); | |||
| 2787 | ||||
| 2788 | /* | |||
| 2789 | * Enable interrupts. | |||
| 2790 | */ | |||
| 2791 | CSR_WRITE_4(sc, DC_IMR, DC_INTRS)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x38), (( 0x00000040|0x00000001|0x00000080|0x00000200| 0x00000002|0x00000004 |0x00000020|0x00002000| 0x00008000|0x00010000 )))); | |||
| 2792 | CSR_WRITE_4(sc, DC_ISR, 0xFFFFFFFF)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x28), (0xFFFFFFFF ))); | |||
| 2793 | ||||
| 2794 | /* Enable transmitter. */ | |||
| 2795 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00002000)))); | |||
| 2796 | ||||
| 2797 | /* | |||
| 2798 | * If this is an Intel 21143 and we're not using the | |||
| 2799 | * MII port, program the LED control pins so we get | |||
| 2800 | * link and activity indications. | |||
| 2801 | */ | |||
| 2802 | if (sc->dc_flags & DC_TULIP_LEDS0x00004000) { | |||
| 2803 | CSR_WRITE_4(sc, DC_WATCHDOG,((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (0x08000000 |0x00800000|0x00200000))) | |||
| 2804 | DC_WDOG_CTLWREN|DC_WDOG_LINK|DC_WDOG_ACTIVITY)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (0x08000000 |0x00800000|0x00200000))); | |||
| 2805 | CSR_WRITE_4(sc, DC_WATCHDOG, 0)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x78), (0 ))); | |||
| 2806 | } | |||
| 2807 | ||||
| 2808 | /* | |||
| 2809 | * Load the RX/multicast filter. We do this sort of late | |||
| 2810 | * because the filter programming scheme on the 21143 and | |||
| 2811 | * some clones requires DMAing a setup frame via the TX | |||
| 2812 | * engine, and we need the transmitter enabled for that. | |||
| 2813 | */ | |||
| 2814 | dc_setfilt(sc); | |||
| 2815 | ||||
| 2816 | /* Enable receiver. */ | |||
| 2817 | DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) | ( 0x00000002)))); | |||
| 2818 | CSR_WRITE_4(sc, DC_RXSTART, 0xFFFFFFFF)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x10), (0xFFFFFFFF ))); | |||
| 2819 | ||||
| 2820 | mii_mediachg(mii); | |||
| 2821 | dc_setcfg(sc, sc->dc_if_media); | |||
| 2822 | ||||
| 2823 | ifp->if_flags |= IFF_RUNNING0x40; | |||
| 2824 | ifq_clr_oactive(&ifp->if_snd); | |||
| 2825 | ||||
| 2826 | splx(s)spllower(s); | |||
| 2827 | ||||
| 2828 | timeout_set(&sc->dc_tick_tmo, dc_tick, sc); | |||
| 2829 | ||||
| 2830 | if (IFM_SUBTYPE(mii->mii_media.ifm_media)((mii->mii_media.ifm_media) & 0x00000000000000ffULL) == IFM_HPNA_117) | |||
| 2831 | sc->dc_link = 1; | |||
| 2832 | else { | |||
| 2833 | if (sc->dc_flags & DC_21143_NWAY0x00000800) | |||
| 2834 | timeout_add_msec(&sc->dc_tick_tmo, 100); | |||
| 2835 | else | |||
| 2836 | timeout_add_sec(&sc->dc_tick_tmo, 1); | |||
| 2837 | } | |||
| 2838 | ||||
| 2839 | #ifdef SRM_MEDIA | |||
| 2840 | if(sc->dc_srm_media) { | |||
| 2841 | struct ifreq ifr; | |||
| 2842 | ||||
| 2843 | ifr.ifr_mediaifr_ifru.ifru_media = sc->dc_srm_media; | |||
| 2844 | ifmedia_ioctl(ifp, &ifr, &mii->mii_media, SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((55)))); | |||
| 2845 | sc->dc_srm_media = 0; | |||
| 2846 | } | |||
| 2847 | #endif | |||
| 2848 | } | |||
| 2849 | ||||
| 2850 | /* | |||
| 2851 | * Set media options. | |||
| 2852 | */ | |||
| 2853 | int | |||
| 2854 | dc_ifmedia_upd(struct ifnet *ifp) | |||
| 2855 | { | |||
| 2856 | struct dc_softc *sc; | |||
| 2857 | struct mii_data *mii; | |||
| 2858 | struct ifmedia *ifm; | |||
| 2859 | ||||
| 2860 | sc = ifp->if_softc; | |||
| 2861 | mii = &sc->sc_mii; | |||
| 2862 | mii_mediachg(mii); | |||
| 2863 | ||||
| 2864 | ifm = &mii->mii_media; | |||
| 2865 | ||||
| 2866 | if (DC_IS_DAVICOM(sc)(sc->dc_type == 0x8) && | |||
| 2867 | IFM_SUBTYPE(ifm->ifm_media)((ifm->ifm_media) & 0x00000000000000ffULL) == IFM_HPNA_117) | |||
| 2868 | dc_setcfg(sc, ifm->ifm_media); | |||
| 2869 | else | |||
| 2870 | sc->dc_link = 0; | |||
| 2871 | ||||
| 2872 | return (0); | |||
| 2873 | } | |||
| 2874 | ||||
| 2875 | /* | |||
| 2876 | * Report current media status. | |||
| 2877 | */ | |||
| 2878 | void | |||
| 2879 | dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) | |||
| 2880 | { | |||
| 2881 | struct dc_softc *sc; | |||
| 2882 | struct mii_data *mii; | |||
| 2883 | struct ifmedia *ifm; | |||
| 2884 | ||||
| 2885 | sc = ifp->if_softc; | |||
| 2886 | mii = &sc->sc_mii; | |||
| 2887 | mii_pollstat(mii); | |||
| 2888 | ifm = &mii->mii_media; | |||
| 2889 | if (DC_IS_DAVICOM(sc)(sc->dc_type == 0x8)) { | |||
| 2890 | if (IFM_SUBTYPE(ifm->ifm_media)((ifm->ifm_media) & 0x00000000000000ffULL) == IFM_HPNA_117) { | |||
| 2891 | ifmr->ifm_active = ifm->ifm_media; | |||
| 2892 | ifmr->ifm_status = 0; | |||
| 2893 | return; | |||
| 2894 | } | |||
| 2895 | } | |||
| 2896 | ifmr->ifm_active = mii->mii_media_active; | |||
| 2897 | ifmr->ifm_status = mii->mii_media_status; | |||
| 2898 | } | |||
| 2899 | ||||
| 2900 | int | |||
| 2901 | dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) | |||
| 2902 | { | |||
| 2903 | struct dc_softc *sc = ifp->if_softc; | |||
| 2904 | struct ifreq *ifr = (struct ifreq *) data; | |||
| 2905 | int s, error = 0; | |||
| 2906 | ||||
| 2907 | s = splnet()splraise(0x7); | |||
| 2908 | ||||
| 2909 | switch(command) { | |||
| 2910 | case SIOCSIFADDR((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((12))): | |||
| 2911 | ifp->if_flags |= IFF_UP0x1; | |||
| 2912 | if (!(ifp->if_flags & IFF_RUNNING0x40)) | |||
| 2913 | dc_init(sc); | |||
| 2914 | break; | |||
| 2915 | case SIOCSIFFLAGS((unsigned long)0x80000000 | ((sizeof(struct ifreq) & 0x1fff ) << 16) | ((('i')) << 8) | ((16))): | |||
| 2916 | if (ifp->if_flags & IFF_UP0x1) { | |||
| 2917 | if (ifp->if_flags & IFF_RUNNING0x40) | |||
| 2918 | error = ENETRESET52; | |||
| 2919 | else { | |||
| 2920 | sc->dc_txthresh = 0; | |||
| 2921 | dc_init(sc); | |||
| 2922 | } | |||
| 2923 | } else { | |||
| 2924 | if (ifp->if_flags & IFF_RUNNING0x40) | |||
| 2925 | dc_stop(sc, 0); | |||
| 2926 | } | |||
| 2927 | break; | |||
| 2928 | case SIOCGIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifmediareq) & 0x1fff) << 16) | ((('i')) << 8) | ((56))): | |||
| 2929 | case SIOCSIFMEDIA(((unsigned long)0x80000000|(unsigned long)0x40000000) | ((sizeof (struct ifreq) & 0x1fff) << 16) | ((('i')) << 8) | ((55))): | |||
| 2930 | error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command); | |||
| 2931 | #ifdef SRM_MEDIA | |||
| 2932 | if (sc->dc_srm_media) | |||
| 2933 | sc->dc_srm_media = 0; | |||
| 2934 | #endif | |||
| 2935 | break; | |||
| 2936 | default: | |||
| 2937 | error = ether_ioctl(ifp, &sc->sc_arpcom, command, data); | |||
| 2938 | } | |||
| 2939 | ||||
| 2940 | if (error == ENETRESET52) { | |||
| 2941 | if (ifp->if_flags & IFF_RUNNING0x40) | |||
| 2942 | dc_setfilt(sc); | |||
| 2943 | error = 0; | |||
| 2944 | } | |||
| 2945 | ||||
| 2946 | splx(s)spllower(s); | |||
| 2947 | return (error); | |||
| 2948 | } | |||
| 2949 | ||||
| 2950 | void | |||
| 2951 | dc_watchdog(struct ifnet *ifp) | |||
| 2952 | { | |||
| 2953 | struct dc_softc *sc; | |||
| 2954 | ||||
| 2955 | sc = ifp->if_softc; | |||
| 2956 | ||||
| 2957 | ifp->if_oerrorsif_data.ifi_oerrors++; | |||
| 2958 | printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname); | |||
| 2959 | ||||
| 2960 | dc_init(sc); | |||
| 2961 | ||||
| 2962 | if (ifq_empty(&ifp->if_snd)(((&ifp->if_snd)->ifq_len) == 0) == 0) | |||
| 2963 | dc_start(ifp); | |||
| 2964 | } | |||
| 2965 | ||||
| 2966 | /* | |||
| 2967 | * Stop the adapter and free any mbufs allocated to the | |||
| 2968 | * RX and TX lists. | |||
| 2969 | */ | |||
| 2970 | void | |||
| 2971 | dc_stop(struct dc_softc *sc, int softonly) | |||
| 2972 | { | |||
| 2973 | struct ifnet *ifp; | |||
| 2974 | u_int32_t isr; | |||
| 2975 | int i; | |||
| 2976 | ||||
| 2977 | ifp = &sc->sc_arpcom.ac_if; | |||
| 2978 | ifp->if_timer = 0; | |||
| 2979 | ||||
| 2980 | timeout_del(&sc->dc_tick_tmo); | |||
| 2981 | ||||
| 2982 | ifp->if_flags &= ~IFF_RUNNING0x40; | |||
| 2983 | ifq_clr_oactive(&ifp->if_snd); | |||
| 2984 | ||||
| 2985 | if (!softonly) { | |||
| 2986 | DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON|DC_NETCFG_TX_ON))((sc->dc_btag)->write_4((sc->dc_bhandle), (0x30), (( (sc->dc_btag)->read_4((sc->dc_bhandle), (0x30))) & ~((0x00000002|0x00002000))))); | |||
| 2987 | ||||
| 2988 | for (i = 0; i < DC_TIMEOUT1000; i++) { | |||
| 2989 | isr = CSR_READ_4(sc, DC_ISR)((sc->dc_btag)->read_4((sc->dc_bhandle), (0x28))); | |||
| 2990 | if ((isr & DC_ISR_TX_IDLE0x00000002 || | |||
| 2991 | (isr & DC_ISR_TX_STATE0x00700000) == DC_TXSTATE_RESET0x00000000) && | |||
| 2992 | (isr & DC_ISR_RX_STATE0x000E0000) == DC_RXSTATE_STOPPED0x00000000) | |||
| 2993 | break; | |||
| 2994 | DELAY(10)(*delay_func)(10); | |||
| 2995 | } | |||
| 2996 | ||||
| 2997 | if (i == DC_TIMEOUT1000) { | |||
| 2998 | if (!((isr & DC_ISR_TX_IDLE0x00000002) || | |||
| 2999 | (isr & DC_ISR_TX_STATE0x00700000) == DC_TXSTATE_RESET0x00000000) && | |||
| 3000 | !DC_IS_ASIX(sc)(sc->dc_type == 0x5) && !DC_IS_DAVICOM(sc)(sc->dc_type == 0x8)) | |||
| 3001 | printf("%s: failed to force tx to idle state\n", | |||
| 3002 | sc->sc_dev.dv_xname); | |||
| 3003 | if (!((isr & DC_ISR_RX_STATE0x000E0000) == DC_RXSTATE_STOPPED0x00000000) && | |||
| 3004 | !DC_HAS_BROKEN_RXSTATE(sc)((sc->dc_type == 0x7) || (sc->dc_type == 0xC) || ((sc-> dc_type == 0x8) && sc->dc_revision >= 0x30))) | |||
| 3005 | printf("%s: failed to force rx to idle state\n", | |||
| 3006 | sc->sc_dev.dv_xname); | |||
| 3007 | } | |||
| 3008 | ||||
| 3009 | CSR_WRITE_4(sc, DC_IMR, 0x00000000)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x38), (0x00000000 ))); | |||
| 3010 | CSR_WRITE_4(sc, DC_TXADDR, 0x00000000)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x20), (0x00000000 ))); | |||
| 3011 | CSR_WRITE_4(sc, DC_RXADDR, 0x00000000)((sc->dc_btag)->write_4((sc->dc_bhandle), (0x18), (0x00000000 ))); | |||
| 3012 | sc->dc_link = 0; | |||
| 3013 | } | |||
| 3014 | ||||
| 3015 | /* | |||
| 3016 | * Free data in the RX lists. | |||
| 3017 | */ | |||
| 3018 | for (i = 0; i < DC_RX_LIST_CNT64; i++) { | |||
| 3019 | if (sc->dc_cdata.dc_rx_chain[i].sd_map->dm_nsegs != 0) { | |||
| 3020 | bus_dmamap_t map = sc->dc_cdata.dc_rx_chain[i].sd_map; | |||
| 3021 | ||||
| 3022 | bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (map), (0), (map->dm_mapsize), (0x02)) | |||
| 3023 | BUS_DMASYNC_POSTREAD)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (map), (0), (map->dm_mapsize), (0x02)); | |||
| 3024 | bus_dmamap_unload(sc->sc_dmat, map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (map )); | |||
| 3025 | } | |||
| 3026 | if (sc->dc_cdata.dc_rx_chain[i].sd_mbuf != NULL((void *)0)) { | |||
| 3027 | m_freem(sc->dc_cdata.dc_rx_chain[i].sd_mbuf); | |||
| 3028 | sc->dc_cdata.dc_rx_chain[i].sd_mbuf = NULL((void *)0); | |||
| 3029 | } | |||
| 3030 | } | |||
| 3031 | bzero(&sc->dc_ldata->dc_rx_list, sizeof(sc->dc_ldata->dc_rx_list))__builtin_bzero((&sc->dc_ldata->dc_rx_list), (sizeof (sc->dc_ldata->dc_rx_list))); | |||
| 3032 | ||||
| 3033 | /* | |||
| 3034 | * Free the TX list buffers. | |||
| 3035 | */ | |||
| 3036 | for (i = 0; i < DC_TX_LIST_CNT256; i++) { | |||
| 3037 | if (sc->dc_cdata.dc_tx_chain[i].sd_map->dm_nsegs != 0) { | |||
| 3038 | bus_dmamap_t map = sc->dc_cdata.dc_tx_chain[i].sd_map; | |||
| 3039 | ||||
| 3040 | bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (map), (0), (map->dm_mapsize), (0x08)) | |||
| 3041 | BUS_DMASYNC_POSTWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (map), (0), (map->dm_mapsize), (0x08)); | |||
| 3042 | bus_dmamap_unload(sc->sc_dmat, map)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (map )); | |||
| 3043 | } | |||
| 3044 | if (sc->dc_cdata.dc_tx_chain[i].sd_mbuf != NULL((void *)0)) { | |||
| 3045 | if (sc->dc_ldata->dc_tx_list[i].dc_ctl & | |||
| 3046 | htole32(DC_TXCTL_SETUP)((__uint32_t)(0x08000000))) { | |||
| 3047 | sc->dc_cdata.dc_tx_chain[i].sd_mbuf = NULL((void *)0); | |||
| 3048 | continue; | |||
| 3049 | } | |||
| 3050 | m_freem(sc->dc_cdata.dc_tx_chain[i].sd_mbuf); | |||
| 3051 | sc->dc_cdata.dc_tx_chain[i].sd_mbuf = NULL((void *)0); | |||
| 3052 | } | |||
| 3053 | } | |||
| 3054 | bzero(&sc->dc_ldata->dc_tx_list, sizeof(sc->dc_ldata->dc_tx_list))__builtin_bzero((&sc->dc_ldata->dc_tx_list), (sizeof (sc->dc_ldata->dc_tx_list))); | |||
| 3055 | ||||
| 3056 | bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (0), (sc->sc_listmap->dm_mapsize), (0x01 | 0x04)) | |||
| 3057 | 0, sc->sc_listmap->dm_mapsize,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (0), (sc->sc_listmap->dm_mapsize), (0x01 | 0x04)) | |||
| 3058 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (sc-> sc_listmap), (0), (sc->sc_listmap->dm_mapsize), (0x01 | 0x04)); | |||
| 3059 | } | |||
| 3060 | ||||
| 3061 | int | |||
| 3062 | dc_activate(struct device *self, int act) | |||
| 3063 | { | |||
| 3064 | struct dc_softc *sc = (struct dc_softc *)self; | |||
| 3065 | struct ifnet *ifp = &sc->sc_arpcom.ac_if; | |||
| 3066 | int rv = 0; | |||
| 3067 | ||||
| 3068 | switch (act) { | |||
| 3069 | case DVACT_SUSPEND3: | |||
| 3070 | if (ifp->if_flags & IFF_RUNNING0x40) | |||
| 3071 | dc_stop(sc, 0); | |||
| 3072 | rv = config_activate_children(self, act); | |||
| 3073 | break; | |||
| 3074 | case DVACT_RESUME4: | |||
| 3075 | if (ifp->if_flags & IFF_UP0x1) | |||
| 3076 | dc_init(sc); | |||
| 3077 | break; | |||
| 3078 | default: | |||
| 3079 | rv = config_activate_children(self, act); | |||
| 3080 | break; | |||
| 3081 | } | |||
| 3082 | return (rv); | |||
| 3083 | } | |||
| 3084 | ||||
| 3085 | int | |||
| 3086 | dc_detach(struct dc_softc *sc) | |||
| 3087 | { | |||
| 3088 | struct ifnet *ifp = &sc->sc_arpcom.ac_if; | |||
| 3089 | int i; | |||
| 3090 | ||||
| 3091 | dc_stop(sc, 1); | |||
| 3092 | ||||
| 3093 | if (LIST_FIRST(&sc->sc_mii.mii_phys)((&sc->sc_mii.mii_phys)->lh_first) != NULL((void *)0)) | |||
| 3094 | mii_detach(&sc->sc_mii, MII_PHY_ANY-1, MII_OFFSET_ANY-1); | |||
| 3095 | ||||
| 3096 | if (sc->dc_srom) | |||
| 3097 | free(sc->dc_srom, M_DEVBUF2, sc->dc_sromsize); | |||
| 3098 | ||||
| 3099 | for (i = 0; i < DC_RX_LIST_CNT64; i++) | |||
| 3100 | bus_dmamap_destroy(sc->sc_dmat, sc->dc_cdata.dc_rx_chain[i].sd_map)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (sc ->dc_cdata.dc_rx_chain[i].sd_map)); | |||
| 3101 | if (sc->sc_rx_sparemap) | |||
| 3102 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_rx_sparemap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (sc ->sc_rx_sparemap)); | |||
| 3103 | for (i = 0; i < DC_TX_LIST_CNT256; i++) | |||
| 3104 | bus_dmamap_destroy(sc->sc_dmat, sc->dc_cdata.dc_tx_chain[i].sd_map)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (sc ->dc_cdata.dc_tx_chain[i].sd_map)); | |||
| 3105 | if (sc->sc_tx_sparemap) | |||
| 3106 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_tx_sparemap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (sc ->sc_tx_sparemap)); | |||
| 3107 | ||||
| 3108 | /// XXX bus_dmamap_sync | |||
| 3109 | bus_dmamap_unload(sc->sc_dmat, sc->sc_listmap)(*(sc->sc_dmat)->_dmamap_unload)((sc->sc_dmat), (sc-> sc_listmap)); | |||
| 3110 | bus_dmamem_unmap(sc->sc_dmat, sc->sc_listkva, sc->sc_listnseg)(*(sc->sc_dmat)->_dmamem_unmap)((sc->sc_dmat), (sc-> sc_listkva), (sc->sc_listnseg)); | |||
| 3111 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_listmap)(*(sc->sc_dmat)->_dmamap_destroy)((sc->sc_dmat), (sc ->sc_listmap)); | |||
| 3112 | bus_dmamem_free(sc->sc_dmat, sc->sc_listseg, sc->sc_listnseg)(*(sc->sc_dmat)->_dmamem_free)((sc->sc_dmat), (sc-> sc_listseg), (sc->sc_listnseg)); | |||
| 3113 | ||||
| 3114 | ether_ifdetach(ifp); | |||
| 3115 | if_detach(ifp); | |||
| 3116 | return (0); | |||
| 3117 | } | |||
| 3118 | ||||
| 3119 | struct cfdriver dc_cd = { | |||
| 3120 | 0, "dc", DV_IFNET | |||
| 3121 | }; |