1 1.119 thorpej /* $NetBSD: if_msk.c,v 1.119 2022/09/24 18:12:42 thorpej Exp $ */ 2 1.68 jdolecek /* $OpenBSD: if_msk.c,v 1.79 2009/10/15 17:54:56 deraadt Exp $ */ 3 1.1 riz 4 1.1 riz /* 5 1.1 riz * Copyright (c) 1997, 1998, 1999, 2000 6 1.1 riz * Bill Paul <wpaul (at) ctr.columbia.edu>. All rights reserved. 7 1.1 riz * 8 1.1 riz * Redistribution and use in source and binary forms, with or without 9 1.1 riz * modification, are permitted provided that the following conditions 10 1.1 riz * are met: 11 1.1 riz * 1. Redistributions of source code must retain the above copyright 12 1.1 riz * notice, this list of conditions and the following disclaimer. 13 1.1 riz * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 riz * notice, this list of conditions and the following disclaimer in the 15 1.1 riz * documentation and/or other materials provided with the distribution. 16 1.1 riz * 3. All advertising materials mentioning features or use of this software 17 1.1 riz * must display the following acknowledgement: 18 1.1 riz * This product includes software developed by Bill Paul. 19 1.1 riz * 4. Neither the name of the author nor the names of any co-contributors 20 1.1 riz * may be used to endorse or promote products derived from this software 21 1.1 riz * without specific prior written permission. 22 1.1 riz * 23 1.1 riz * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 24 1.1 riz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 1.1 riz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 1.1 riz * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 27 1.1 riz * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 1.1 riz * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 1.1 riz * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 1.1 riz * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31 1.1 riz * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 1.1 riz * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 33 1.1 riz * THE POSSIBILITY OF SUCH DAMAGE. 34 1.1 riz * 35 1.1 riz * $FreeBSD: /c/ncvs/src/sys/pci/if_sk.c,v 1.20 2000/04/22 02:16:37 wpaul Exp $ 36 1.1 riz */ 37 1.1 riz 38 1.1 riz /* 39 1.1 riz * Copyright (c) 2003 Nathan L. Binkert <binkertn (at) umich.edu> 40 1.1 riz * 41 1.1 riz * Permission to use, copy, modify, and distribute this software for any 42 1.1 riz * purpose with or without fee is hereby granted, provided that the above 43 1.1 riz * copyright notice and this permission notice appear in all copies. 44 1.1 riz * 45 1.1 riz * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 46 1.1 riz * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 47 1.1 riz * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 48 1.1 riz * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 49 1.1 riz * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 50 1.1 riz * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 51 1.1 riz * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 52 1.1 riz */ 53 1.1 riz 54 1.10 dsl #include <sys/cdefs.h> 55 1.119 thorpej __KERNEL_RCSID(0, "$NetBSD: if_msk.c,v 1.119 2022/09/24 18:12:42 thorpej Exp $"); 56 1.1 riz 57 1.1 riz #include <sys/param.h> 58 1.1 riz #include <sys/systm.h> 59 1.1 riz #include <sys/sockio.h> 60 1.1 riz #include <sys/mbuf.h> 61 1.21 cube #include <sys/mutex.h> 62 1.1 riz #include <sys/kernel.h> 63 1.1 riz #include <sys/socket.h> 64 1.1 riz #include <sys/device.h> 65 1.1 riz #include <sys/queue.h> 66 1.1 riz #include <sys/callout.h> 67 1.1 riz #include <sys/sysctl.h> 68 1.1 riz #include <sys/endian.h> 69 1.1 riz #ifdef __NetBSD__ 70 1.103 jakllsch #define letoh16 le16toh 71 1.103 jakllsch #define letoh32 le32toh 72 1.1 riz #endif 73 1.1 riz 74 1.1 riz #include <net/if.h> 75 1.1 riz #include <net/if_dl.h> 76 1.1 riz #include <net/if_types.h> 77 1.1 riz 78 1.1 riz #include <net/if_media.h> 79 1.1 riz 80 1.1 riz #include <net/bpf.h> 81 1.48 riastrad #include <sys/rndsource.h> 82 1.1 riz 83 1.1 riz #include <dev/mii/mii.h> 84 1.1 riz #include <dev/mii/miivar.h> 85 1.1 riz 86 1.1 riz #include <dev/pci/pcireg.h> 87 1.1 riz #include <dev/pci/pcivar.h> 88 1.1 riz #include <dev/pci/pcidevs.h> 89 1.1 riz 90 1.1 riz #include <dev/pci/if_skreg.h> 91 1.1 riz #include <dev/pci/if_mskvar.h> 92 1.1 riz 93 1.95 maxv static int mskc_probe(device_t, cfdata_t, void *); 94 1.95 maxv static void mskc_attach(device_t, device_t, void *); 95 1.95 maxv static int mskc_detach(device_t, int); 96 1.95 maxv static void mskc_reset(struct sk_softc *); 97 1.33 dyoung static bool mskc_suspend(device_t, const pmf_qual_t *); 98 1.33 dyoung static bool mskc_resume(device_t, const pmf_qual_t *); 99 1.95 maxv static int msk_probe(device_t, cfdata_t, void *); 100 1.95 maxv static void msk_attach(device_t, device_t, void *); 101 1.95 maxv static int msk_detach(device_t, int); 102 1.95 maxv static void msk_reset(struct sk_if_softc *); 103 1.95 maxv static int mskcprint(void *, const char *); 104 1.95 maxv static int msk_intr(void *); 105 1.95 maxv static void msk_intr_yukon(struct sk_if_softc *); 106 1.95 maxv static void msk_rxeof(struct sk_if_softc *, uint16_t, uint32_t); 107 1.95 maxv static void msk_txeof(struct sk_if_softc *); 108 1.95 maxv static int msk_encap(struct sk_if_softc *, struct mbuf *, uint32_t *); 109 1.95 maxv static void msk_start(struct ifnet *); 110 1.95 maxv static int msk_ioctl(struct ifnet *, u_long, void *); 111 1.95 maxv static int msk_init(struct ifnet *); 112 1.95 maxv static void msk_init_yukon(struct sk_if_softc *); 113 1.95 maxv static void msk_stop(struct ifnet *, int); 114 1.95 maxv static void msk_watchdog(struct ifnet *); 115 1.106 jakllsch static int msk_newbuf(struct sk_if_softc *); 116 1.95 maxv static int msk_alloc_jumbo_mem(struct sk_if_softc *); 117 1.95 maxv static void *msk_jalloc(struct sk_if_softc *); 118 1.95 maxv static void msk_jfree(struct mbuf *, void *, size_t, void *); 119 1.95 maxv static int msk_init_rx_ring(struct sk_if_softc *); 120 1.95 maxv static int msk_init_tx_ring(struct sk_if_softc *); 121 1.95 maxv static void msk_fill_rx_ring(struct sk_if_softc *); 122 1.95 maxv 123 1.95 maxv static void msk_update_int_mod(struct sk_softc *, int); 124 1.95 maxv 125 1.95 maxv static int msk_miibus_readreg(device_t, int, int, uint16_t *); 126 1.95 maxv static int msk_miibus_writereg(device_t, int, int, uint16_t); 127 1.95 maxv static void msk_miibus_statchg(struct ifnet *); 128 1.95 maxv 129 1.95 maxv static void msk_setmulti(struct sk_if_softc *); 130 1.95 maxv static void msk_setpromisc(struct sk_if_softc *); 131 1.95 maxv static void msk_tick(void *); 132 1.72 jdolecek static void msk_fill_rx_tick(void *); 133 1.1 riz 134 1.1 riz /* #define MSK_DEBUG 1 */ 135 1.1 riz #ifdef MSK_DEBUG 136 1.1 riz #define DPRINTF(x) if (mskdebug) printf x 137 1.88 msaitoh #define DPRINTFN(n, x) if (mskdebug >= (n)) printf x 138 1.1 riz int mskdebug = MSK_DEBUG; 139 1.1 riz 140 1.96 maxv static void msk_dump_txdesc(struct msk_tx_desc *, int); 141 1.96 maxv static void msk_dump_mbuf(struct mbuf *); 142 1.96 maxv static void msk_dump_bytes(const char *, int); 143 1.1 riz #else 144 1.1 riz #define DPRINTF(x) 145 1.88 msaitoh #define DPRINTFN(n, x) 146 1.1 riz #endif 147 1.1 riz 148 1.1 riz static int msk_sysctl_handler(SYSCTLFN_PROTO); 149 1.1 riz static int msk_root_num; 150 1.1 riz 151 1.89 msaitoh #define MSK_ADDR_LO(x) ((uint64_t) (x) & 0xffffffffUL) 152 1.89 msaitoh #define MSK_ADDR_HI(x) ((uint64_t) (x) >> 32) 153 1.78 jakllsch 154 1.1 riz /* supported device vendors */ 155 1.116 thorpej static const struct device_compatible_entry compat_data[] = { 156 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_DLINK, 157 1.116 thorpej PCI_PRODUCT_DLINK_DGE550SX) }, 158 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_DLINK, 159 1.116 thorpej PCI_PRODUCT_DLINK_DGE550T_B1) }, 160 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_DLINK, 161 1.116 thorpej PCI_PRODUCT_DLINK_DGE560SX) }, 162 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_DLINK, 163 1.116 thorpej PCI_PRODUCT_DLINK_DGE560T) }, 164 1.116 thorpej 165 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 166 1.116 thorpej PCI_PRODUCT_MARVELL_YUKONII_8021CU) }, 167 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 168 1.116 thorpej PCI_PRODUCT_MARVELL_YUKONII_8021X) }, 169 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 170 1.116 thorpej PCI_PRODUCT_MARVELL_YUKONII_8022CU) }, 171 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 172 1.116 thorpej PCI_PRODUCT_MARVELL_YUKONII_8022X) }, 173 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 174 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8035) }, 175 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 176 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8036) }, 177 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 178 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8038) }, 179 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 180 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8039) }, 181 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 182 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8040) }, 183 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 184 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8040T) }, 185 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 186 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8042) }, 187 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 188 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8048) }, 189 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 190 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8050) }, 191 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 192 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8052) }, 193 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 194 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8053) }, 195 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 196 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8055) }, 197 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 198 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8055_2) }, 199 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 200 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8056) }, 201 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 202 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8057) }, 203 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 204 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8058) }, 205 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 206 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8059) }, 207 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 208 1.116 thorpej PCI_PRODUCT_MARVELL_YUKONII_8061CU) }, 209 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 210 1.116 thorpej PCI_PRODUCT_MARVELL_YUKONII_8061X) }, 211 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 212 1.116 thorpej PCI_PRODUCT_MARVELL_YUKONII_8062CU) }, 213 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 214 1.116 thorpej PCI_PRODUCT_MARVELL_YUKONII_8062X) }, 215 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 216 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8070) }, 217 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 218 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8071) }, 219 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 220 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8072) }, 221 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 222 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8075) }, 223 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 224 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_8079) }, 225 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 226 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_C032) }, 227 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 228 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_C033) }, 229 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 230 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_C034) }, 231 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 232 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_C036) }, 233 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 234 1.116 thorpej PCI_PRODUCT_MARVELL_YUKON_C042) }, 235 1.116 thorpej 236 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_SCHNEIDERKOCH, 237 1.116 thorpej PCI_PRODUCT_SCHNEIDERKOCH_SK_9SXX) }, 238 1.116 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_SCHNEIDERKOCH, 239 1.116 thorpej PCI_PRODUCT_SCHNEIDERKOCH_SK_9E21) }, 240 1.116 thorpej 241 1.116 thorpej PCI_COMPAT_EOL 242 1.1 riz }; 243 1.1 riz 244 1.83 msaitoh static inline uint32_t 245 1.83 msaitoh sk_win_read_4(struct sk_softc *sc, uint32_t reg) 246 1.1 riz { 247 1.1 riz return CSR_READ_4(sc, reg); 248 1.1 riz } 249 1.1 riz 250 1.83 msaitoh static inline uint16_t 251 1.83 msaitoh sk_win_read_2(struct sk_softc *sc, uint32_t reg) 252 1.1 riz { 253 1.1 riz return CSR_READ_2(sc, reg); 254 1.1 riz } 255 1.1 riz 256 1.83 msaitoh static inline uint8_t 257 1.83 msaitoh sk_win_read_1(struct sk_softc *sc, uint32_t reg) 258 1.1 riz { 259 1.1 riz return CSR_READ_1(sc, reg); 260 1.1 riz } 261 1.1 riz 262 1.1 riz static inline void 263 1.83 msaitoh sk_win_write_4(struct sk_softc *sc, uint32_t reg, uint32_t x) 264 1.1 riz { 265 1.1 riz CSR_WRITE_4(sc, reg, x); 266 1.1 riz } 267 1.1 riz 268 1.1 riz static inline void 269 1.83 msaitoh sk_win_write_2(struct sk_softc *sc, uint32_t reg, uint16_t x) 270 1.1 riz { 271 1.1 riz CSR_WRITE_2(sc, reg, x); 272 1.1 riz } 273 1.1 riz 274 1.1 riz static inline void 275 1.83 msaitoh sk_win_write_1(struct sk_softc *sc, uint32_t reg, uint8_t x) 276 1.1 riz { 277 1.1 riz CSR_WRITE_1(sc, reg, x); 278 1.1 riz } 279 1.1 riz 280 1.95 maxv static int 281 1.84 msaitoh msk_miibus_readreg(device_t dev, int phy, int reg, uint16_t *val) 282 1.1 riz { 283 1.27 cegger struct sk_if_softc *sc_if = device_private(dev); 284 1.84 msaitoh uint16_t data; 285 1.1 riz int i; 286 1.1 riz 287 1.59 jdolecek SK_YU_WRITE_2(sc_if, YUKON_SMICR, YU_SMICR_PHYAD(phy) | 288 1.1 riz YU_SMICR_REGAD(reg) | YU_SMICR_OP_READ); 289 1.65 msaitoh 290 1.1 riz for (i = 0; i < SK_TIMEOUT; i++) { 291 1.1 riz DELAY(1); 292 1.84 msaitoh data = SK_YU_READ_2(sc_if, YUKON_SMICR); 293 1.84 msaitoh if (data & YU_SMICR_READ_VALID) 294 1.1 riz break; 295 1.1 riz } 296 1.1 riz 297 1.1 riz if (i == SK_TIMEOUT) { 298 1.114 jakllsch device_printf(sc_if->sk_dev, "phy failed to come ready\n"); 299 1.84 msaitoh return ETIMEDOUT; 300 1.1 riz } 301 1.65 msaitoh 302 1.89 msaitoh DPRINTFN(9, ("msk_miibus_readreg: i=%d, timeout=%d\n", i, SK_TIMEOUT)); 303 1.1 riz 304 1.84 msaitoh *val = SK_YU_READ_2(sc_if, YUKON_SMIDR); 305 1.1 riz 306 1.84 msaitoh DPRINTFN(9, ("msk_miibus_readreg phy=%d, reg=%#x, val=%#hx\n", 307 1.84 msaitoh phy, reg, *val)); 308 1.1 riz 309 1.84 msaitoh return 0; 310 1.1 riz } 311 1.1 riz 312 1.95 maxv static int 313 1.84 msaitoh msk_miibus_writereg(device_t dev, int phy, int reg, uint16_t val) 314 1.1 riz { 315 1.27 cegger struct sk_if_softc *sc_if = device_private(dev); 316 1.1 riz int i; 317 1.1 riz 318 1.84 msaitoh DPRINTFN(9, ("msk_miibus_writereg phy=%d reg=%#x val=%#hx\n", 319 1.1 riz phy, reg, val)); 320 1.1 riz 321 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_SMIDR, val); 322 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_SMICR, YU_SMICR_PHYAD(phy) | 323 1.1 riz YU_SMICR_REGAD(reg) | YU_SMICR_OP_WRITE); 324 1.1 riz 325 1.1 riz for (i = 0; i < SK_TIMEOUT; i++) { 326 1.1 riz DELAY(1); 327 1.4 msaitoh if (!(SK_YU_READ_2(sc_if, YUKON_SMICR) & YU_SMICR_BUSY)) 328 1.1 riz break; 329 1.1 riz } 330 1.1 riz 331 1.84 msaitoh if (i == SK_TIMEOUT) { 332 1.114 jakllsch device_printf(sc_if->sk_dev, "phy write timed out\n"); 333 1.84 msaitoh return ETIMEDOUT; 334 1.84 msaitoh } 335 1.84 msaitoh 336 1.84 msaitoh return 0; 337 1.1 riz } 338 1.1 riz 339 1.95 maxv static void 340 1.41 matt msk_miibus_statchg(struct ifnet *ifp) 341 1.1 riz { 342 1.41 matt struct sk_if_softc *sc_if = ifp->if_softc; 343 1.5 msaitoh struct mii_data *mii = &sc_if->sk_mii; 344 1.5 msaitoh struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 345 1.5 msaitoh int gpcr; 346 1.5 msaitoh 347 1.5 msaitoh gpcr = SK_YU_READ_2(sc_if, YUKON_GPCR); 348 1.5 msaitoh gpcr &= (YU_GPCR_TXEN | YU_GPCR_RXEN); 349 1.5 msaitoh 350 1.60 jdolecek if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO || 351 1.60 jdolecek sc_if->sk_softc->sk_type == SK_YUKON_FE_P) { 352 1.5 msaitoh /* Set speed. */ 353 1.5 msaitoh gpcr |= YU_GPCR_SPEED_DIS; 354 1.5 msaitoh switch (IFM_SUBTYPE(mii->mii_media_active)) { 355 1.5 msaitoh case IFM_1000_SX: 356 1.5 msaitoh case IFM_1000_LX: 357 1.5 msaitoh case IFM_1000_CX: 358 1.5 msaitoh case IFM_1000_T: 359 1.5 msaitoh gpcr |= (YU_GPCR_GIG | YU_GPCR_SPEED); 360 1.5 msaitoh break; 361 1.5 msaitoh case IFM_100_TX: 362 1.5 msaitoh gpcr |= YU_GPCR_SPEED; 363 1.5 msaitoh break; 364 1.5 msaitoh } 365 1.5 msaitoh 366 1.5 msaitoh /* Set duplex. */ 367 1.5 msaitoh gpcr |= YU_GPCR_DPLX_DIS; 368 1.87 msaitoh if ((mii->mii_media_active & IFM_FDX) != 0) 369 1.5 msaitoh gpcr |= YU_GPCR_DUPLEX; 370 1.5 msaitoh 371 1.5 msaitoh /* Disable flow control. */ 372 1.5 msaitoh gpcr |= YU_GPCR_FCTL_DIS; 373 1.5 msaitoh gpcr |= (YU_GPCR_FCTL_TX_DIS | YU_GPCR_FCTL_RX_DIS); 374 1.5 msaitoh } 375 1.5 msaitoh 376 1.5 msaitoh SK_YU_WRITE_2(sc_if, YUKON_GPCR, gpcr); 377 1.5 msaitoh 378 1.5 msaitoh DPRINTFN(9, ("msk_miibus_statchg: gpcr=%x\n", 379 1.41 matt SK_YU_READ_2(sc_if, YUKON_GPCR))); 380 1.1 riz } 381 1.1 riz 382 1.95 maxv static void 383 1.1 riz msk_setmulti(struct sk_if_softc *sc_if) 384 1.1 riz { 385 1.1 riz struct ifnet *ifp= &sc_if->sk_ethercom.ec_if; 386 1.83 msaitoh uint32_t hashes[2] = { 0, 0 }; 387 1.1 riz int h; 388 1.1 riz struct ethercom *ec = &sc_if->sk_ethercom; 389 1.1 riz struct ether_multi *enm; 390 1.1 riz struct ether_multistep step; 391 1.83 msaitoh uint16_t reg; 392 1.1 riz 393 1.1 riz /* First, zot all the existing filters. */ 394 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_MCAH1, 0); 395 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_MCAH2, 0); 396 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_MCAH3, 0); 397 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_MCAH4, 0); 398 1.1 riz 399 1.1 riz 400 1.1 riz /* Now program new ones. */ 401 1.6 msaitoh reg = SK_YU_READ_2(sc_if, YUKON_RCR); 402 1.6 msaitoh reg |= YU_RCR_UFLEN; 403 1.1 riz allmulti: 404 1.1 riz if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 405 1.6 msaitoh if ((ifp->if_flags & IFF_PROMISC) != 0) 406 1.6 msaitoh reg &= ~(YU_RCR_UFLEN | YU_RCR_MUFLEN); 407 1.6 msaitoh else if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 408 1.6 msaitoh hashes[0] = 0xFFFFFFFF; 409 1.6 msaitoh hashes[1] = 0xFFFFFFFF; 410 1.6 msaitoh } 411 1.1 riz } else { 412 1.1 riz /* First find the tail of the list. */ 413 1.90 msaitoh ETHER_LOCK(ec); 414 1.1 riz ETHER_FIRST_MULTI(step, ec, enm); 415 1.1 riz while (enm != NULL) { 416 1.23 cegger if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 417 1.1 riz ETHER_ADDR_LEN)) { 418 1.1 riz ifp->if_flags |= IFF_ALLMULTI; 419 1.90 msaitoh ETHER_UNLOCK(ec); 420 1.1 riz goto allmulti; 421 1.1 riz } 422 1.5 msaitoh h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) & 423 1.61 jdolecek ((1 << SK_HASH_BITS) - 1); 424 1.1 riz if (h < 32) 425 1.1 riz hashes[0] |= (1 << h); 426 1.1 riz else 427 1.1 riz hashes[1] |= (1 << (h - 32)); 428 1.1 riz 429 1.1 riz ETHER_NEXT_MULTI(step, enm); 430 1.1 riz } 431 1.90 msaitoh ETHER_UNLOCK(ec); 432 1.6 msaitoh reg |= YU_RCR_MUFLEN; 433 1.1 riz } 434 1.1 riz 435 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_MCAH1, hashes[0] & 0xffff); 436 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_MCAH2, (hashes[0] >> 16) & 0xffff); 437 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_MCAH3, hashes[1] & 0xffff); 438 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_MCAH4, (hashes[1] >> 16) & 0xffff); 439 1.6 msaitoh SK_YU_WRITE_2(sc_if, YUKON_RCR, reg); 440 1.1 riz } 441 1.1 riz 442 1.95 maxv static void 443 1.1 riz msk_setpromisc(struct sk_if_softc *sc_if) 444 1.1 riz { 445 1.1 riz struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; 446 1.1 riz 447 1.1 riz if (ifp->if_flags & IFF_PROMISC) 448 1.1 riz SK_YU_CLRBIT_2(sc_if, YUKON_RCR, 449 1.1 riz YU_RCR_UFLEN | YU_RCR_MUFLEN); 450 1.1 riz else 451 1.1 riz SK_YU_SETBIT_2(sc_if, YUKON_RCR, 452 1.1 riz YU_RCR_UFLEN | YU_RCR_MUFLEN); 453 1.1 riz } 454 1.1 riz 455 1.95 maxv static int 456 1.1 riz msk_init_rx_ring(struct sk_if_softc *sc_if) 457 1.1 riz { 458 1.1 riz struct msk_chain_data *cd = &sc_if->sk_cdata; 459 1.1 riz struct msk_ring_data *rd = sc_if->sk_rdata; 460 1.78 jakllsch struct msk_rx_desc *r; 461 1.1 riz 462 1.30 christos memset(rd->sk_rx_ring, 0, sizeof(struct msk_rx_desc) * MSK_RX_RING_CNT); 463 1.1 riz 464 1.68 jdolecek sc_if->sk_cdata.sk_rx_prod = 0; 465 1.1 riz sc_if->sk_cdata.sk_rx_cons = 0; 466 1.68 jdolecek sc_if->sk_cdata.sk_rx_cnt = 0; 467 1.82 mrg sc_if->sk_cdata.sk_rx_hiaddr = 0; 468 1.1 riz 469 1.78 jakllsch /* Mark the first ring element to initialize the high address. */ 470 1.78 jakllsch sc_if->sk_cdata.sk_rx_hiaddr = 0; 471 1.78 jakllsch r = &rd->sk_rx_ring[cd->sk_rx_prod]; 472 1.78 jakllsch r->sk_addr = htole32(cd->sk_rx_hiaddr); 473 1.78 jakllsch r->sk_len = 0; 474 1.78 jakllsch r->sk_ctl = 0; 475 1.78 jakllsch r->sk_opcode = SK_Y2_BMUOPC_ADDR64 | SK_Y2_RXOPC_OWN; 476 1.78 jakllsch MSK_CDRXSYNC(sc_if, cd->sk_rx_prod, 477 1.88 msaitoh BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 478 1.78 jakllsch SK_INC(sc_if->sk_cdata.sk_rx_prod, MSK_RX_RING_CNT); 479 1.78 jakllsch sc_if->sk_cdata.sk_rx_cnt++; 480 1.78 jakllsch 481 1.68 jdolecek msk_fill_rx_ring(sc_if); 482 1.88 msaitoh return 0; 483 1.1 riz } 484 1.1 riz 485 1.95 maxv static int 486 1.1 riz msk_init_tx_ring(struct sk_if_softc *sc_if) 487 1.1 riz { 488 1.1 riz struct msk_chain_data *cd = &sc_if->sk_cdata; 489 1.1 riz struct msk_ring_data *rd = sc_if->sk_rdata; 490 1.78 jakllsch struct msk_tx_desc *t; 491 1.1 riz 492 1.66 msaitoh memset(rd->sk_tx_ring, 0, sizeof(struct msk_tx_desc) * MSK_TX_RING_CNT); 493 1.1 riz 494 1.1 riz sc_if->sk_cdata.sk_tx_prod = 0; 495 1.1 riz sc_if->sk_cdata.sk_tx_cons = 0; 496 1.1 riz sc_if->sk_cdata.sk_tx_cnt = 0; 497 1.82 mrg sc_if->sk_cdata.sk_tx_hiaddr = 0; 498 1.1 riz 499 1.78 jakllsch /* Mark the first ring element to initialize the high address. */ 500 1.78 jakllsch sc_if->sk_cdata.sk_tx_hiaddr = 0; 501 1.78 jakllsch t = &rd->sk_tx_ring[cd->sk_tx_prod]; 502 1.78 jakllsch t->sk_addr = htole32(cd->sk_tx_hiaddr); 503 1.78 jakllsch t->sk_len = 0; 504 1.78 jakllsch t->sk_ctl = 0; 505 1.78 jakllsch t->sk_opcode = SK_Y2_BMUOPC_ADDR64 | SK_Y2_TXOPC_OWN; 506 1.1 riz MSK_CDTXSYNC(sc_if, 0, MSK_TX_RING_CNT, 507 1.88 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 508 1.78 jakllsch SK_INC(sc_if->sk_cdata.sk_tx_prod, MSK_TX_RING_CNT); 509 1.78 jakllsch sc_if->sk_cdata.sk_tx_cnt++; 510 1.1 riz 511 1.88 msaitoh return 0; 512 1.1 riz } 513 1.1 riz 514 1.95 maxv static int 515 1.106 jakllsch msk_newbuf(struct sk_if_softc *sc_if) 516 1.1 riz { 517 1.106 jakllsch struct sk_softc *sc = sc_if->sk_softc; 518 1.1 riz struct mbuf *m_new = NULL; 519 1.1 riz struct sk_chain *c; 520 1.1 riz struct msk_rx_desc *r; 521 1.78 jakllsch void *buf = NULL; 522 1.78 jakllsch bus_addr_t addr; 523 1.106 jakllsch bus_dmamap_t rxmap; 524 1.106 jakllsch size_t i; 525 1.109 jakllsch uint32_t rxidx, frag, cur, hiaddr, total; 526 1.106 jakllsch uint32_t entries = 0; 527 1.109 jakllsch uint8_t own = 0; 528 1.1 riz 529 1.72 jdolecek MGETHDR(m_new, M_DONTWAIT, MT_DATA); 530 1.72 jdolecek if (m_new == NULL) 531 1.88 msaitoh return ENOBUFS; 532 1.1 riz 533 1.72 jdolecek /* Allocate the jumbo buffer */ 534 1.72 jdolecek buf = msk_jalloc(sc_if); 535 1.72 jdolecek if (buf == NULL) { 536 1.72 jdolecek m_freem(m_new); 537 1.72 jdolecek DPRINTFN(1, ("%s jumbo allocation failed -- packet " 538 1.72 jdolecek "dropped!\n", sc_if->sk_ethercom.ec_if.if_xname)); 539 1.88 msaitoh return ENOBUFS; 540 1.72 jdolecek } 541 1.65 msaitoh 542 1.72 jdolecek /* Attach the buffer to the mbuf */ 543 1.72 jdolecek m_new->m_len = m_new->m_pkthdr.len = SK_JLEN; 544 1.72 jdolecek MEXTADD(m_new, buf, SK_JLEN, 0, msk_jfree, sc_if); 545 1.1 riz 546 1.1 riz m_adj(m_new, ETHER_ALIGN); 547 1.1 riz 548 1.106 jakllsch rxidx = frag = cur = sc_if->sk_cdata.sk_rx_prod; 549 1.106 jakllsch rxmap = sc_if->sk_cdata.sk_rx_chain[rxidx].sk_dmamap; 550 1.78 jakllsch 551 1.106 jakllsch if (bus_dmamap_load_mbuf(sc->sc_dmatag, rxmap, m_new, BUS_DMA_NOWAIT)) { 552 1.106 jakllsch DPRINTFN(2, ("msk_newbuf: dmamap_load failed\n")); 553 1.106 jakllsch m_freem(m_new); 554 1.106 jakllsch return ENOBUFS; 555 1.106 jakllsch } 556 1.78 jakllsch 557 1.106 jakllsch /* Count how many rx descriptors needed. */ 558 1.106 jakllsch hiaddr = sc_if->sk_cdata.sk_rx_hiaddr; 559 1.106 jakllsch for (total = i = 0; i < rxmap->dm_nsegs; i++) { 560 1.106 jakllsch if (hiaddr != MSK_ADDR_HI(rxmap->dm_segs[i].ds_addr)) { 561 1.106 jakllsch hiaddr = MSK_ADDR_HI(rxmap->dm_segs[i].ds_addr); 562 1.106 jakllsch total++; 563 1.106 jakllsch } 564 1.106 jakllsch total++; 565 1.106 jakllsch } 566 1.78 jakllsch 567 1.106 jakllsch if (total > MSK_RX_RING_CNT - sc_if->sk_cdata.sk_rx_cnt - 1) { 568 1.106 jakllsch DPRINTFN(2, ("msk_newbuf: too few descriptors free\n")); 569 1.106 jakllsch bus_dmamap_unload(sc->sc_dmatag, rxmap); 570 1.106 jakllsch m_freem(m_new); 571 1.106 jakllsch return ENOBUFS; 572 1.78 jakllsch } 573 1.78 jakllsch 574 1.106 jakllsch DPRINTFN(2, ("msk_newbuf: dm_nsegs=%d total desc=%u\n", 575 1.106 jakllsch rxmap->dm_nsegs, total)); 576 1.106 jakllsch 577 1.106 jakllsch /* Sync the DMA map. */ 578 1.106 jakllsch bus_dmamap_sync(sc->sc_dmatag, rxmap, 0, rxmap->dm_mapsize, 579 1.106 jakllsch BUS_DMASYNC_PREREAD); 580 1.106 jakllsch 581 1.106 jakllsch for (i = 0; i < rxmap->dm_nsegs; i++) { 582 1.106 jakllsch addr = rxmap->dm_segs[i].ds_addr; 583 1.106 jakllsch DPRINTFN(2, ("msk_newbuf: addr %llx\n", 584 1.106 jakllsch (unsigned long long)addr)); 585 1.106 jakllsch hiaddr = MSK_ADDR_HI(addr); 586 1.106 jakllsch 587 1.106 jakllsch if (sc_if->sk_cdata.sk_rx_hiaddr != hiaddr) { 588 1.106 jakllsch c = &sc_if->sk_cdata.sk_rx_chain[frag]; 589 1.106 jakllsch c->sk_mbuf = NULL; 590 1.106 jakllsch r = &sc_if->sk_rdata->sk_rx_ring[frag]; 591 1.106 jakllsch r->sk_addr = htole32(hiaddr); 592 1.106 jakllsch r->sk_len = 0; 593 1.106 jakllsch r->sk_ctl = 0; 594 1.109 jakllsch r->sk_opcode = SK_Y2_BMUOPC_ADDR64 | own; 595 1.109 jakllsch own = SK_Y2_RXOPC_OWN; 596 1.106 jakllsch sc_if->sk_cdata.sk_rx_hiaddr = hiaddr; 597 1.106 jakllsch MSK_CDRXSYNC(sc_if, frag, 598 1.106 jakllsch BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 599 1.106 jakllsch SK_INC(frag, MSK_RX_RING_CNT); 600 1.106 jakllsch entries++; 601 1.106 jakllsch DPRINTFN(10, ("%s: rx ADDR64: %#x\n", 602 1.106 jakllsch sc_if->sk_ethercom.ec_if.if_xname, hiaddr)); 603 1.106 jakllsch } 604 1.106 jakllsch 605 1.106 jakllsch c = &sc_if->sk_cdata.sk_rx_chain[frag]; 606 1.106 jakllsch r = &sc_if->sk_rdata->sk_rx_ring[frag]; 607 1.106 jakllsch r->sk_addr = htole32(MSK_ADDR_LO(addr)); 608 1.106 jakllsch r->sk_len = htole16(rxmap->dm_segs[i].ds_len); 609 1.106 jakllsch r->sk_ctl = 0; 610 1.106 jakllsch if (i == 0) { 611 1.109 jakllsch r->sk_opcode = SK_Y2_RXOPC_PACKET | own; 612 1.106 jakllsch } else 613 1.109 jakllsch r->sk_opcode = SK_Y2_RXOPC_BUFFER | own; 614 1.109 jakllsch own = SK_Y2_RXOPC_OWN; 615 1.106 jakllsch MSK_CDRXSYNC(sc_if, frag, 616 1.106 jakllsch BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 617 1.106 jakllsch cur = frag; 618 1.106 jakllsch SK_INC(frag, MSK_RX_RING_CNT); 619 1.106 jakllsch entries++; 620 1.106 jakllsch } 621 1.106 jakllsch KASSERTMSG(entries == total, "entries %u total %u", entries, total); 622 1.106 jakllsch 623 1.106 jakllsch sc_if->sk_cdata.sk_rx_chain[rxidx].sk_dmamap = 624 1.106 jakllsch sc_if->sk_cdata.sk_rx_chain[cur].sk_dmamap; 625 1.106 jakllsch sc_if->sk_cdata.sk_rx_chain[cur].sk_mbuf = m_new; 626 1.106 jakllsch sc_if->sk_cdata.sk_rx_chain[cur].sk_dmamap = rxmap; 627 1.1 riz 628 1.106 jakllsch sc_if->sk_rdata->sk_rx_ring[rxidx].sk_opcode |= SK_Y2_RXOPC_OWN; 629 1.106 jakllsch MSK_CDRXSYNC(sc_if, rxidx, 630 1.88 msaitoh BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 631 1.68 jdolecek 632 1.106 jakllsch sc_if->sk_cdata.sk_rx_cnt += entries; 633 1.106 jakllsch sc_if->sk_cdata.sk_rx_prod = frag; 634 1.1 riz 635 1.88 msaitoh return 0; 636 1.1 riz } 637 1.1 riz 638 1.1 riz /* 639 1.1 riz * Memory management for jumbo frames. 640 1.1 riz */ 641 1.1 riz 642 1.95 maxv static int 643 1.1 riz msk_alloc_jumbo_mem(struct sk_if_softc *sc_if) 644 1.1 riz { 645 1.1 riz struct sk_softc *sc = sc_if->sk_softc; 646 1.8 christos char *ptr, *kva; 647 1.70 jdolecek int i, state, error; 648 1.89 msaitoh struct sk_jpool_entry *entry; 649 1.1 riz 650 1.1 riz state = error = 0; 651 1.1 riz 652 1.1 riz /* Grab a big chunk o' storage. */ 653 1.1 riz if (bus_dmamem_alloc(sc->sc_dmatag, MSK_JMEM, PAGE_SIZE, 0, 654 1.70 jdolecek &sc_if->sk_cdata.sk_jumbo_seg, 1, &sc_if->sk_cdata.sk_jumbo_nseg, 655 1.70 jdolecek BUS_DMA_NOWAIT)) { 656 1.1 riz aprint_error(": can't alloc rx buffers"); 657 1.88 msaitoh return ENOBUFS; 658 1.1 riz } 659 1.1 riz 660 1.1 riz state = 1; 661 1.70 jdolecek if (bus_dmamem_map(sc->sc_dmatag, &sc_if->sk_cdata.sk_jumbo_seg, 662 1.70 jdolecek sc_if->sk_cdata.sk_jumbo_nseg, MSK_JMEM, (void **)&kva, 663 1.118 jmcneill BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) { 664 1.1 riz aprint_error(": can't map dma buffers (%d bytes)", MSK_JMEM); 665 1.1 riz error = ENOBUFS; 666 1.1 riz goto out; 667 1.1 riz } 668 1.1 riz 669 1.1 riz state = 2; 670 1.1 riz if (bus_dmamap_create(sc->sc_dmatag, MSK_JMEM, 1, MSK_JMEM, 0, 671 1.1 riz BUS_DMA_NOWAIT, &sc_if->sk_cdata.sk_rx_jumbo_map)) { 672 1.1 riz aprint_error(": can't create dma map"); 673 1.1 riz error = ENOBUFS; 674 1.1 riz goto out; 675 1.1 riz } 676 1.1 riz 677 1.1 riz state = 3; 678 1.1 riz if (bus_dmamap_load(sc->sc_dmatag, sc_if->sk_cdata.sk_rx_jumbo_map, 679 1.1 riz kva, MSK_JMEM, NULL, BUS_DMA_NOWAIT)) { 680 1.1 riz aprint_error(": can't load dma map"); 681 1.1 riz error = ENOBUFS; 682 1.1 riz goto out; 683 1.1 riz } 684 1.1 riz 685 1.1 riz state = 4; 686 1.8 christos sc_if->sk_cdata.sk_jumbo_buf = (void *)kva; 687 1.83 msaitoh DPRINTFN(1,("msk_jumbo_buf = %p\n", 688 1.83 msaitoh (void *)sc_if->sk_cdata.sk_jumbo_buf)); 689 1.1 riz 690 1.1 riz LIST_INIT(&sc_if->sk_jfree_listhead); 691 1.1 riz LIST_INIT(&sc_if->sk_jinuse_listhead); 692 1.21 cube mutex_init(&sc_if->sk_jpool_mtx, MUTEX_DEFAULT, IPL_NET); 693 1.1 riz 694 1.1 riz /* 695 1.1 riz * Now divide it up into 9K pieces and save the addresses 696 1.1 riz * in an array. 697 1.1 riz */ 698 1.1 riz ptr = sc_if->sk_cdata.sk_jumbo_buf; 699 1.1 riz for (i = 0; i < MSK_JSLOTS; i++) { 700 1.1 riz sc_if->sk_cdata.sk_jslots[i] = ptr; 701 1.1 riz ptr += SK_JLEN; 702 1.1 riz entry = malloc(sizeof(struct sk_jpool_entry), 703 1.93 chs M_DEVBUF, M_WAITOK); 704 1.1 riz entry->slot = i; 705 1.5 msaitoh LIST_INSERT_HEAD(&sc_if->sk_jfree_listhead, 706 1.1 riz entry, jpool_entries); 707 1.1 riz } 708 1.1 riz out: 709 1.1 riz if (error != 0) { 710 1.1 riz switch (state) { 711 1.1 riz case 4: 712 1.1 riz bus_dmamap_unload(sc->sc_dmatag, 713 1.1 riz sc_if->sk_cdata.sk_rx_jumbo_map); 714 1.86 mrg /* FALLTHROUGH */ 715 1.1 riz case 3: 716 1.1 riz bus_dmamap_destroy(sc->sc_dmatag, 717 1.1 riz sc_if->sk_cdata.sk_rx_jumbo_map); 718 1.86 mrg /* FALLTHROUGH */ 719 1.1 riz case 2: 720 1.1 riz bus_dmamem_unmap(sc->sc_dmatag, kva, MSK_JMEM); 721 1.86 mrg /* FALLTHROUGH */ 722 1.1 riz case 1: 723 1.70 jdolecek bus_dmamem_free(sc->sc_dmatag, 724 1.70 jdolecek &sc_if->sk_cdata.sk_jumbo_seg, 725 1.70 jdolecek sc_if->sk_cdata.sk_jumbo_nseg); 726 1.1 riz break; 727 1.1 riz default: 728 1.1 riz break; 729 1.1 riz } 730 1.1 riz } 731 1.1 riz 732 1.52 christos return error; 733 1.1 riz } 734 1.1 riz 735 1.70 jdolecek static void 736 1.70 jdolecek msk_free_jumbo_mem(struct sk_if_softc *sc_if) 737 1.70 jdolecek { 738 1.70 jdolecek struct sk_softc *sc = sc_if->sk_softc; 739 1.70 jdolecek 740 1.70 jdolecek bus_dmamap_unload(sc->sc_dmatag, sc_if->sk_cdata.sk_rx_jumbo_map); 741 1.70 jdolecek bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_cdata.sk_rx_jumbo_map); 742 1.70 jdolecek bus_dmamem_unmap(sc->sc_dmatag, sc_if->sk_cdata.sk_jumbo_buf, MSK_JMEM); 743 1.70 jdolecek bus_dmamem_free(sc->sc_dmatag, &sc_if->sk_cdata.sk_jumbo_seg, 744 1.70 jdolecek sc_if->sk_cdata.sk_jumbo_nseg); 745 1.70 jdolecek } 746 1.70 jdolecek 747 1.1 riz /* 748 1.1 riz * Allocate a jumbo buffer. 749 1.1 riz */ 750 1.95 maxv static void * 751 1.1 riz msk_jalloc(struct sk_if_softc *sc_if) 752 1.1 riz { 753 1.89 msaitoh struct sk_jpool_entry *entry; 754 1.1 riz 755 1.21 cube mutex_enter(&sc_if->sk_jpool_mtx); 756 1.1 riz entry = LIST_FIRST(&sc_if->sk_jfree_listhead); 757 1.1 riz 758 1.21 cube if (entry == NULL) { 759 1.21 cube mutex_exit(&sc_if->sk_jpool_mtx); 760 1.21 cube return NULL; 761 1.21 cube } 762 1.1 riz 763 1.1 riz LIST_REMOVE(entry, jpool_entries); 764 1.1 riz LIST_INSERT_HEAD(&sc_if->sk_jinuse_listhead, entry, jpool_entries); 765 1.21 cube mutex_exit(&sc_if->sk_jpool_mtx); 766 1.88 msaitoh return sc_if->sk_cdata.sk_jslots[entry->slot]; 767 1.1 riz } 768 1.1 riz 769 1.1 riz /* 770 1.1 riz * Release a jumbo buffer. 771 1.1 riz */ 772 1.95 maxv static void 773 1.8 christos msk_jfree(struct mbuf *m, void *buf, size_t size, void *arg) 774 1.1 riz { 775 1.1 riz struct sk_jpool_entry *entry; 776 1.1 riz struct sk_if_softc *sc; 777 1.21 cube int i; 778 1.1 riz 779 1.1 riz /* Extract the softc struct pointer. */ 780 1.1 riz sc = (struct sk_if_softc *)arg; 781 1.1 riz 782 1.1 riz if (sc == NULL) 783 1.1 riz panic("msk_jfree: can't find softc pointer!"); 784 1.1 riz 785 1.1 riz /* calculate the slot this buffer belongs to */ 786 1.1 riz i = ((vaddr_t)buf 787 1.1 riz - (vaddr_t)sc->sk_cdata.sk_jumbo_buf) / SK_JLEN; 788 1.1 riz 789 1.1 riz if ((i < 0) || (i >= MSK_JSLOTS)) 790 1.6 msaitoh panic("msk_jfree: asked to free buffer that we don't manage!"); 791 1.1 riz 792 1.21 cube mutex_enter(&sc->sk_jpool_mtx); 793 1.1 riz entry = LIST_FIRST(&sc->sk_jinuse_listhead); 794 1.1 riz if (entry == NULL) 795 1.1 riz panic("msk_jfree: buffer not in use!"); 796 1.1 riz entry->slot = i; 797 1.1 riz LIST_REMOVE(entry, jpool_entries); 798 1.1 riz LIST_INSERT_HEAD(&sc->sk_jfree_listhead, entry, jpool_entries); 799 1.21 cube mutex_exit(&sc->sk_jpool_mtx); 800 1.1 riz 801 1.1 riz if (__predict_true(m != NULL)) 802 1.12 ad pool_cache_put(mb_cache, m); 803 1.72 jdolecek 804 1.72 jdolecek /* Now that we know we have a free RX buffer, refill if running out */ 805 1.72 jdolecek if ((sc->sk_ethercom.ec_if.if_flags & IFF_RUNNING) != 0 806 1.72 jdolecek && sc->sk_cdata.sk_rx_cnt < (MSK_RX_RING_CNT/3)) 807 1.72 jdolecek callout_schedule(&sc->sk_tick_rx, 0); 808 1.1 riz } 809 1.1 riz 810 1.95 maxv static int 811 1.19 dyoung msk_ioctl(struct ifnet *ifp, u_long cmd, void *data) 812 1.1 riz { 813 1.52 christos struct sk_if_softc *sc = ifp->if_softc; 814 1.52 christos int s, error; 815 1.1 riz 816 1.1 riz s = splnet(); 817 1.1 riz 818 1.78 jakllsch DPRINTFN(2, ("msk_ioctl ETHER cmd %lx\n", cmd)); 819 1.52 christos switch (cmd) { 820 1.52 christos case SIOCSIFFLAGS: 821 1.52 christos if ((error = ifioctl_common(ifp, cmd, data)) != 0) 822 1.52 christos break; 823 1.1 riz 824 1.52 christos switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { 825 1.52 christos case IFF_RUNNING: 826 1.52 christos msk_stop(ifp, 1); 827 1.52 christos break; 828 1.52 christos case IFF_UP: 829 1.52 christos msk_init(ifp); 830 1.52 christos break; 831 1.52 christos case IFF_UP | IFF_RUNNING: 832 1.52 christos if ((ifp->if_flags ^ sc->sk_if_flags) == IFF_PROMISC) { 833 1.52 christos msk_setpromisc(sc); 834 1.52 christos msk_setmulti(sc); 835 1.52 christos } else 836 1.52 christos msk_init(ifp); 837 1.52 christos break; 838 1.1 riz } 839 1.52 christos sc->sk_if_flags = ifp->if_flags; 840 1.52 christos break; 841 1.52 christos default: 842 1.52 christos error = ether_ioctl(ifp, cmd, data); 843 1.52 christos if (error == ENETRESET) { 844 1.52 christos error = 0; 845 1.52 christos if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI) 846 1.52 christos ; 847 1.52 christos else if (ifp->if_flags & IFF_RUNNING) { 848 1.52 christos /* 849 1.52 christos * Multicast list has changed; set the hardware 850 1.52 christos * filter accordingly. 851 1.52 christos */ 852 1.52 christos msk_setmulti(sc); 853 1.52 christos } 854 1.52 christos } 855 1.52 christos break; 856 1.1 riz } 857 1.1 riz 858 1.1 riz splx(s); 859 1.52 christos return error; 860 1.1 riz } 861 1.1 riz 862 1.95 maxv static void 863 1.30 christos msk_update_int_mod(struct sk_softc *sc, int verbose) 864 1.1 riz { 865 1.83 msaitoh uint32_t imtimer_ticks; 866 1.1 riz 867 1.1 riz /* 868 1.1 riz * Configure interrupt moderation. The moderation timer 869 1.1 riz * defers interrupts specified in the interrupt moderation 870 1.1 riz * timer mask based on the timeout specified in the interrupt 871 1.1 riz * moderation timer init register. Each bit in the timer 872 1.1 riz * register represents one tick, so to specify a timeout in 873 1.1 riz * microseconds, we have to multiply by the correct number of 874 1.1 riz * ticks-per-microsecond. 875 1.1 riz */ 876 1.1 riz switch (sc->sk_type) { 877 1.1 riz case SK_YUKON_EC: 878 1.6 msaitoh case SK_YUKON_EC_U: 879 1.56 jdolecek case SK_YUKON_EX: 880 1.56 jdolecek case SK_YUKON_SUPR: 881 1.56 jdolecek case SK_YUKON_ULTRA2: 882 1.56 jdolecek case SK_YUKON_OPTIMA: 883 1.56 jdolecek case SK_YUKON_PRM: 884 1.56 jdolecek case SK_YUKON_OPTIMA2: 885 1.5 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON_EC; 886 1.1 riz break; 887 1.6 msaitoh case SK_YUKON_FE: 888 1.6 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON_FE; 889 1.6 msaitoh break; 890 1.68 jdolecek case SK_YUKON_FE_P: 891 1.68 jdolecek imtimer_ticks = SK_IMTIMER_TICKS_YUKON_FE_P; 892 1.68 jdolecek break; 893 1.6 msaitoh case SK_YUKON_XL: 894 1.6 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON_XL; 895 1.6 msaitoh break; 896 1.1 riz default: 897 1.5 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON; 898 1.1 riz } 899 1.30 christos if (verbose) 900 1.30 christos aprint_verbose_dev(sc->sk_dev, 901 1.30 christos "interrupt moderation is %d us\n", sc->sk_int_mod); 902 1.59 jdolecek sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(sc->sk_int_mod)); 903 1.111 jakllsch sk_win_write_4(sc, SK_IMMR, 0); /* moderate no interrupts */ 904 1.59 jdolecek sk_win_write_1(sc, SK_IMTIMERCTL, SK_IMCTL_START); 905 1.1 riz sc->sk_int_mod_pending = 0; 906 1.1 riz } 907 1.1 riz 908 1.1 riz /* 909 1.1 riz * Probe for a SysKonnect GEnesis chip. Check the PCI vendor and device 910 1.1 riz * IDs against our list and return a device name if we find a match. 911 1.1 riz */ 912 1.95 maxv static int 913 1.26 cegger mskc_probe(device_t parent, cfdata_t match, void *aux) 914 1.1 riz { 915 1.1 riz struct pci_attach_args *pa = (struct pci_attach_args *)aux; 916 1.1 riz 917 1.116 thorpej return pci_compatible_match(pa, compat_data); 918 1.1 riz } 919 1.1 riz 920 1.1 riz /* 921 1.1 riz * Force the GEnesis into reset, then bring it out of reset. 922 1.1 riz */ 923 1.95 maxv static void 924 1.63 jdolecek mskc_reset(struct sk_softc *sc) 925 1.1 riz { 926 1.83 msaitoh uint32_t imtimer_ticks, reg1; 927 1.94 msaitoh uint16_t status; 928 1.1 riz int reg; 929 1.1 riz 930 1.63 jdolecek DPRINTFN(2, ("mskc_reset\n")); 931 1.1 riz 932 1.94 msaitoh /* Disable ASF */ 933 1.94 msaitoh if ((sc->sk_type == SK_YUKON_EX) || (sc->sk_type == SK_YUKON_SUPR)) { 934 1.94 msaitoh CSR_WRITE_4(sc, SK_Y2_CPU_WDOG, 0); 935 1.94 msaitoh status = CSR_READ_2(sc, SK_Y2_ASF_HCU_CCSR); 936 1.94 msaitoh /* Clear AHB bridge & microcontroller reset. */ 937 1.94 msaitoh status &= ~(SK_Y2_ASF_HCU_CSSR_ARB_RST | 938 1.94 msaitoh SK_Y2_ASF_HCU_CSSR_CPU_RST_MODE); 939 1.94 msaitoh /* Clear ASF microcontroller state. */ 940 1.94 msaitoh status &= ~SK_Y2_ASF_HCU_CSSR_UC_STATE_MSK; 941 1.94 msaitoh status &= ~SK_Y2_ASF_HCU_CSSR_CPU_CLK_DIVIDE_MSK; 942 1.94 msaitoh CSR_WRITE_2(sc, SK_Y2_ASF_HCU_CCSR, status); 943 1.94 msaitoh CSR_WRITE_4(sc, SK_Y2_CPU_WDOG, 0); 944 1.94 msaitoh } else 945 1.94 msaitoh CSR_WRITE_1(sc, SK_Y2_ASF_CSR, SK_Y2_ASF_RESET); 946 1.94 msaitoh CSR_WRITE_2(sc, SK_CSR, SK_CSR_ASF_OFF); 947 1.94 msaitoh 948 1.1 riz CSR_WRITE_1(sc, SK_CSR, SK_CSR_SW_RESET); 949 1.1 riz CSR_WRITE_1(sc, SK_CSR, SK_CSR_MASTER_RESET); 950 1.1 riz 951 1.1 riz DELAY(1000); 952 1.1 riz CSR_WRITE_1(sc, SK_CSR, SK_CSR_SW_UNRESET); 953 1.1 riz DELAY(2); 954 1.1 riz CSR_WRITE_1(sc, SK_CSR, SK_CSR_MASTER_UNRESET); 955 1.5 msaitoh sk_win_write_1(sc, SK_TESTCTL1, 2); 956 1.5 msaitoh 957 1.56 jdolecek if (sc->sk_type == SK_YUKON_EC_U || sc->sk_type == SK_YUKON_EX || 958 1.56 jdolecek sc->sk_type >= SK_YUKON_FE_P) { 959 1.22 chris uint32_t our; 960 1.22 chris 961 1.22 chris CSR_WRITE_2(sc, SK_CSR, SK_CSR_WOL_ON); 962 1.65 msaitoh 963 1.22 chris /* enable all clocks. */ 964 1.22 chris sk_win_write_4(sc, SK_Y2_PCI_REG(SK_PCI_OURREG3), 0); 965 1.22 chris our = sk_win_read_4(sc, SK_Y2_PCI_REG(SK_PCI_OURREG4)); 966 1.88 msaitoh our &= (SK_Y2_REG4_FORCE_ASPM_REQUEST | 967 1.88 msaitoh SK_Y2_REG4_ASPM_GPHY_LINK_DOWN | 968 1.88 msaitoh SK_Y2_REG4_ASPM_INT_FIFO_EMPTY | 969 1.22 chris SK_Y2_REG4_ASPM_CLKRUN_REQUEST); 970 1.43 christos /* Set all bits to 0 except bits 15..12 */ 971 1.22 chris sk_win_write_4(sc, SK_Y2_PCI_REG(SK_PCI_OURREG4), our); 972 1.22 chris /* Set to default value */ 973 1.22 chris sk_win_write_4(sc, SK_Y2_PCI_REG(SK_PCI_OURREG5), 0); 974 1.74 jdolecek 975 1.74 jdolecek /* 976 1.74 jdolecek * Disable status race, workaround for Yukon EC Ultra & 977 1.74 jdolecek * Yukon EX. 978 1.74 jdolecek */ 979 1.74 jdolecek reg1 = sk_win_read_4(sc, SK_GPIO); 980 1.74 jdolecek reg1 |= SK_Y2_GPIO_STAT_RACE_DIS; 981 1.74 jdolecek sk_win_write_4(sc, SK_GPIO, reg1); 982 1.74 jdolecek sk_win_read_4(sc, SK_GPIO); 983 1.22 chris } 984 1.22 chris 985 1.22 chris /* release PHY from PowerDown/Coma mode. */ 986 1.60 jdolecek reg1 = sk_win_read_4(sc, SK_Y2_PCI_REG(SK_PCI_OURREG1)); 987 1.60 jdolecek if (sc->sk_type == SK_YUKON_XL && sc->sk_rev > SK_YUKON_XL_REV_A1) 988 1.60 jdolecek reg1 |= (SK_Y2_REG1_PHY1_COMA | SK_Y2_REG1_PHY2_COMA); 989 1.60 jdolecek else 990 1.60 jdolecek reg1 &= ~(SK_Y2_REG1_PHY1_COMA | SK_Y2_REG1_PHY2_COMA); 991 1.5 msaitoh sk_win_write_4(sc, SK_Y2_PCI_REG(SK_PCI_OURREG1), reg1); 992 1.43 christos 993 1.5 msaitoh if (sc->sk_type == SK_YUKON_XL && sc->sk_rev > SK_YUKON_XL_REV_A1) 994 1.5 msaitoh sk_win_write_1(sc, SK_Y2_CLKGATE, 995 1.5 msaitoh SK_Y2_CLKGATE_LINK1_GATE_DIS | 996 1.5 msaitoh SK_Y2_CLKGATE_LINK2_GATE_DIS | 997 1.5 msaitoh SK_Y2_CLKGATE_LINK1_CORE_DIS | 998 1.5 msaitoh SK_Y2_CLKGATE_LINK2_CORE_DIS | 999 1.5 msaitoh SK_Y2_CLKGATE_LINK1_PCI_DIS | SK_Y2_CLKGATE_LINK2_PCI_DIS); 1000 1.5 msaitoh else 1001 1.5 msaitoh sk_win_write_1(sc, SK_Y2_CLKGATE, 0); 1002 1.43 christos 1003 1.5 msaitoh CSR_WRITE_2(sc, SK_LINK_CTRL, SK_LINK_RESET_SET); 1004 1.5 msaitoh CSR_WRITE_2(sc, SK_LINK_CTRL + SK_WIN_LEN, SK_LINK_RESET_SET); 1005 1.5 msaitoh DELAY(1000); 1006 1.1 riz CSR_WRITE_2(sc, SK_LINK_CTRL, SK_LINK_RESET_CLEAR); 1007 1.5 msaitoh CSR_WRITE_2(sc, SK_LINK_CTRL + SK_WIN_LEN, SK_LINK_RESET_CLEAR); 1008 1.5 msaitoh 1009 1.56 jdolecek if (sc->sk_type == SK_YUKON_EX || sc->sk_type == SK_YUKON_SUPR) { 1010 1.56 jdolecek CSR_WRITE_2(sc, SK_GMAC_CTRL, SK_GMAC_BYP_MACSECRX | 1011 1.56 jdolecek SK_GMAC_BYP_MACSECTX | SK_GMAC_BYP_RETR_FIFO); 1012 1.59 jdolecek } 1013 1.56 jdolecek 1014 1.5 msaitoh sk_win_write_1(sc, SK_TESTCTL1, 1); 1015 1.1 riz 1016 1.63 jdolecek DPRINTFN(2, ("mskc_reset: sk_csr=%x\n", CSR_READ_1(sc, SK_CSR))); 1017 1.63 jdolecek DPRINTFN(2, ("mskc_reset: sk_link_ctrl=%x\n", 1018 1.1 riz CSR_READ_2(sc, SK_LINK_CTRL))); 1019 1.1 riz 1020 1.1 riz /* Clear I2C IRQ noise */ 1021 1.1 riz CSR_WRITE_4(sc, SK_I2CHWIRQ, 1); 1022 1.1 riz 1023 1.1 riz /* Disable hardware timer */ 1024 1.1 riz CSR_WRITE_1(sc, SK_TIMERCTL, SK_IMCTL_STOP); 1025 1.1 riz CSR_WRITE_1(sc, SK_TIMERCTL, SK_IMCTL_IRQ_CLEAR); 1026 1.1 riz 1027 1.1 riz /* Disable descriptor polling */ 1028 1.1 riz CSR_WRITE_4(sc, SK_DPT_TIMER_CTRL, SK_DPT_TCTL_STOP); 1029 1.1 riz 1030 1.1 riz /* Disable time stamps */ 1031 1.1 riz CSR_WRITE_1(sc, SK_TSTAMP_CTL, SK_TSTAMP_STOP); 1032 1.1 riz CSR_WRITE_1(sc, SK_TSTAMP_CTL, SK_TSTAMP_IRQ_CLEAR); 1033 1.1 riz 1034 1.1 riz /* Enable RAM interface */ 1035 1.1 riz sk_win_write_1(sc, SK_RAMCTL, SK_RAMCTL_UNRESET); 1036 1.1 riz for (reg = SK_TO0;reg <= SK_TO11; reg++) 1037 1.1 riz sk_win_write_1(sc, reg, 36); 1038 1.5 msaitoh sk_win_write_1(sc, SK_RAMCTL + (SK_WIN_LEN / 2), SK_RAMCTL_UNRESET); 1039 1.5 msaitoh for (reg = SK_TO0;reg <= SK_TO11; reg++) 1040 1.5 msaitoh sk_win_write_1(sc, reg + (SK_WIN_LEN / 2), 36); 1041 1.1 riz 1042 1.1 riz /* 1043 1.1 riz * Configure interrupt moderation. The moderation timer 1044 1.1 riz * defers interrupts specified in the interrupt moderation 1045 1.1 riz * timer mask based on the timeout specified in the interrupt 1046 1.1 riz * moderation timer init register. Each bit in the timer 1047 1.1 riz * register represents one tick, so to specify a timeout in 1048 1.1 riz * microseconds, we have to multiply by the correct number of 1049 1.1 riz * ticks-per-microsecond. 1050 1.1 riz */ 1051 1.1 riz switch (sc->sk_type) { 1052 1.1 riz case SK_YUKON_EC: 1053 1.6 msaitoh case SK_YUKON_EC_U: 1054 1.60 jdolecek case SK_YUKON_EX: 1055 1.60 jdolecek case SK_YUKON_SUPR: 1056 1.60 jdolecek case SK_YUKON_ULTRA2: 1057 1.60 jdolecek case SK_YUKON_OPTIMA: 1058 1.60 jdolecek case SK_YUKON_PRM: 1059 1.60 jdolecek case SK_YUKON_OPTIMA2: 1060 1.6 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON_EC; 1061 1.6 msaitoh break; 1062 1.6 msaitoh case SK_YUKON_FE: 1063 1.6 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON_FE; 1064 1.6 msaitoh break; 1065 1.60 jdolecek case SK_YUKON_FE_P: 1066 1.60 jdolecek imtimer_ticks = SK_IMTIMER_TICKS_YUKON_FE_P; 1067 1.60 jdolecek break; 1068 1.1 riz case SK_YUKON_XL: 1069 1.6 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON_XL; 1070 1.1 riz break; 1071 1.1 riz default: 1072 1.5 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON; 1073 1.60 jdolecek break; 1074 1.1 riz } 1075 1.1 riz 1076 1.1 riz /* Reset status ring. */ 1077 1.30 christos memset(sc->sk_status_ring, 0, 1078 1.1 riz MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)); 1079 1.17 kiyohara bus_dmamap_sync(sc->sc_dmatag, sc->sk_status_map, 0, 1080 1.17 kiyohara sc->sk_status_map->dm_mapsize, BUS_DMASYNC_PREREAD); 1081 1.1 riz sc->sk_status_idx = 0; 1082 1.1 riz 1083 1.1 riz sk_win_write_4(sc, SK_STAT_BMU_CSR, SK_STAT_BMU_RESET); 1084 1.1 riz sk_win_write_4(sc, SK_STAT_BMU_CSR, SK_STAT_BMU_UNRESET); 1085 1.1 riz 1086 1.1 riz sk_win_write_2(sc, SK_STAT_BMU_LIDX, MSK_STATUS_RING_CNT - 1); 1087 1.1 riz sk_win_write_4(sc, SK_STAT_BMU_ADDRLO, 1088 1.82 mrg MSK_ADDR_LO(sc->sk_status_map->dm_segs[0].ds_addr)); 1089 1.1 riz sk_win_write_4(sc, SK_STAT_BMU_ADDRHI, 1090 1.82 mrg MSK_ADDR_HI(sc->sk_status_map->dm_segs[0].ds_addr)); 1091 1.75 jdolecek if (sc->sk_type == SK_YUKON_EC && 1092 1.75 jdolecek sc->sk_rev == SK_YUKON_EC_REV_A1) { 1093 1.75 jdolecek /* WA for dev. #4.3 */ 1094 1.83 msaitoh sk_win_write_2(sc, SK_STAT_BMU_TX_THRESH, 1095 1.83 msaitoh SK_STAT_BMU_TXTHIDX_MSK); 1096 1.75 jdolecek /* WA for dev. #4.18 */ 1097 1.6 msaitoh sk_win_write_1(sc, SK_STAT_BMU_FIFOWM, 0x21); 1098 1.6 msaitoh sk_win_write_1(sc, SK_STAT_BMU_FIFOIWM, 0x07); 1099 1.6 msaitoh } else { 1100 1.6 msaitoh sk_win_write_2(sc, SK_STAT_BMU_TX_THRESH, 0x000a); 1101 1.6 msaitoh sk_win_write_1(sc, SK_STAT_BMU_FIFOWM, 0x10); 1102 1.75 jdolecek if (sc->sk_type == SK_YUKON_XL) 1103 1.75 jdolecek sk_win_write_1(sc, SK_STAT_BMU_FIFOIWM, 0x04); 1104 1.75 jdolecek else 1105 1.75 jdolecek sk_win_write_1(sc, SK_STAT_BMU_FIFOIWM, 0x10); 1106 1.6 msaitoh sk_win_write_4(sc, SK_Y2_ISR_ITIMERINIT, 0x0190); /* 3.2us on Yukon-EC */ 1107 1.6 msaitoh } 1108 1.1 riz 1109 1.1 riz #if 0 1110 1.1 riz sk_win_write_4(sc, SK_Y2_LEV_ITIMERINIT, SK_IM_USECS(100)); 1111 1.6 msaitoh #endif 1112 1.1 riz sk_win_write_4(sc, SK_Y2_TX_ITIMERINIT, SK_IM_USECS(1000)); 1113 1.1 riz 1114 1.75 jdolecek /* Enable status unit. */ 1115 1.1 riz sk_win_write_4(sc, SK_STAT_BMU_CSR, SK_STAT_BMU_ON); 1116 1.1 riz 1117 1.1 riz sk_win_write_1(sc, SK_Y2_LEV_ITIMERCTL, SK_IMCTL_START); 1118 1.1 riz sk_win_write_1(sc, SK_Y2_TX_ITIMERCTL, SK_IMCTL_START); 1119 1.1 riz sk_win_write_1(sc, SK_Y2_ISR_ITIMERCTL, SK_IMCTL_START); 1120 1.1 riz 1121 1.30 christos msk_update_int_mod(sc, 0); 1122 1.1 riz } 1123 1.1 riz 1124 1.95 maxv static int 1125 1.26 cegger msk_probe(device_t parent, cfdata_t match, void *aux) 1126 1.1 riz { 1127 1.1 riz struct skc_attach_args *sa = aux; 1128 1.1 riz 1129 1.1 riz if (sa->skc_port != SK_PORT_A && sa->skc_port != SK_PORT_B) 1130 1.88 msaitoh return 0; 1131 1.1 riz 1132 1.1 riz switch (sa->skc_type) { 1133 1.1 riz case SK_YUKON_XL: 1134 1.1 riz case SK_YUKON_EC_U: 1135 1.56 jdolecek case SK_YUKON_EX: 1136 1.1 riz case SK_YUKON_EC: 1137 1.1 riz case SK_YUKON_FE: 1138 1.47 christos case SK_YUKON_FE_P: 1139 1.56 jdolecek case SK_YUKON_SUPR: 1140 1.56 jdolecek case SK_YUKON_ULTRA2: 1141 1.56 jdolecek case SK_YUKON_OPTIMA: 1142 1.56 jdolecek case SK_YUKON_PRM: 1143 1.56 jdolecek case SK_YUKON_OPTIMA2: 1144 1.88 msaitoh return 1; 1145 1.1 riz } 1146 1.1 riz 1147 1.88 msaitoh return 0; 1148 1.1 riz } 1149 1.1 riz 1150 1.95 maxv static void 1151 1.63 jdolecek msk_reset(struct sk_if_softc *sc_if) 1152 1.63 jdolecek { 1153 1.63 jdolecek /* GMAC and GPHY Reset */ 1154 1.63 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_RESET_SET); 1155 1.94 msaitoh SK_IF_WRITE_1(sc_if, 0, SK_GPHY_CTRL, SK_GPHY_RESET_SET); 1156 1.63 jdolecek DELAY(1000); 1157 1.94 msaitoh SK_IF_WRITE_1(sc_if, 0, SK_GPHY_CTRL, SK_GPHY_RESET_CLEAR); 1158 1.63 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_LOOP_OFF | 1159 1.63 jdolecek SK_GMAC_PAUSE_ON | SK_GMAC_RESET_CLEAR); 1160 1.63 jdolecek } 1161 1.63 jdolecek 1162 1.20 joerg static bool 1163 1.33 dyoung msk_resume(device_t dv, const pmf_qual_t *qual) 1164 1.20 joerg { 1165 1.20 joerg struct sk_if_softc *sc_if = device_private(dv); 1166 1.43 christos 1167 1.20 joerg msk_init_yukon(sc_if); 1168 1.20 joerg return true; 1169 1.20 joerg } 1170 1.20 joerg 1171 1.1 riz /* 1172 1.1 riz * Each XMAC chip is attached as a separate logical IP interface. 1173 1.1 riz * Single port cards will have only one logical interface of course. 1174 1.1 riz */ 1175 1.95 maxv static void 1176 1.26 cegger msk_attach(device_t parent, device_t self, void *aux) 1177 1.1 riz { 1178 1.27 cegger struct sk_if_softc *sc_if = device_private(self); 1179 1.27 cegger struct sk_softc *sc = device_private(parent); 1180 1.1 riz struct skc_attach_args *sa = aux; 1181 1.99 jakllsch bus_dmamap_t dmamap; 1182 1.1 riz struct ifnet *ifp; 1183 1.88 msaitoh struct mii_data * const mii = &sc_if->sk_mii; 1184 1.8 christos void *kva; 1185 1.63 jdolecek int i; 1186 1.83 msaitoh uint32_t chunk; 1187 1.63 jdolecek int mii_flags; 1188 1.1 riz 1189 1.30 christos sc_if->sk_dev = self; 1190 1.1 riz sc_if->sk_port = sa->skc_port; 1191 1.1 riz sc_if->sk_softc = sc; 1192 1.1 riz sc->sk_if[sa->skc_port] = sc_if; 1193 1.1 riz 1194 1.1 riz DPRINTFN(2, ("begin msk_attach: port=%d\n", sc_if->sk_port)); 1195 1.1 riz 1196 1.1 riz /* 1197 1.1 riz * Get station address for this interface. Note that 1198 1.1 riz * dual port cards actually come with three station 1199 1.1 riz * addresses: one for each port, plus an extra. The 1200 1.1 riz * extra one is used by the SysKonnect driver software 1201 1.1 riz * as a 'virtual' station address for when both ports 1202 1.1 riz * are operating in failover mode. Currently we don't 1203 1.1 riz * use this extra address. 1204 1.1 riz */ 1205 1.1 riz for (i = 0; i < ETHER_ADDR_LEN; i++) 1206 1.1 riz sc_if->sk_enaddr[i] = 1207 1.1 riz sk_win_read_1(sc, SK_MAC0_0 + (sa->skc_port * 8) + i); 1208 1.1 riz 1209 1.1 riz aprint_normal(": Ethernet address %s\n", 1210 1.1 riz ether_sprintf(sc_if->sk_enaddr)); 1211 1.1 riz 1212 1.1 riz /* 1213 1.57 jdolecek * Set up RAM buffer addresses. The Yukon2 has a small amount 1214 1.57 jdolecek * of SRAM on it, somewhere between 4K and 48K. We need to 1215 1.57 jdolecek * divide this up between the transmitter and receiver. We 1216 1.57 jdolecek * give the receiver 2/3 of the memory (rounded down), and the 1217 1.57 jdolecek * transmitter whatever remains. 1218 1.1 riz */ 1219 1.78 jakllsch if (sc->sk_ramsize) { 1220 1.83 msaitoh chunk = (2 * (sc->sk_ramsize / sizeof(uint64_t)) / 3) & ~0xff; 1221 1.78 jakllsch sc_if->sk_rx_ramstart = 0; 1222 1.78 jakllsch sc_if->sk_rx_ramend = sc_if->sk_rx_ramstart + chunk - 1; 1223 1.83 msaitoh chunk = (sc->sk_ramsize / sizeof(uint64_t)) - chunk; 1224 1.78 jakllsch sc_if->sk_tx_ramstart = sc_if->sk_rx_ramend + 1; 1225 1.78 jakllsch sc_if->sk_tx_ramend = sc_if->sk_tx_ramstart + chunk - 1; 1226 1.78 jakllsch 1227 1.78 jakllsch DPRINTFN(2, ("msk_attach: rx_ramstart=%#x rx_ramend=%#x\n" 1228 1.78 jakllsch " tx_ramstart=%#x tx_ramend=%#x\n", 1229 1.78 jakllsch sc_if->sk_rx_ramstart, sc_if->sk_rx_ramend, 1230 1.78 jakllsch sc_if->sk_tx_ramstart, sc_if->sk_tx_ramend)); 1231 1.78 jakllsch } 1232 1.1 riz 1233 1.1 riz /* Allocate the descriptor queues. */ 1234 1.1 riz if (bus_dmamem_alloc(sc->sc_dmatag, sizeof(struct msk_ring_data), 1235 1.63 jdolecek PAGE_SIZE, 0, &sc_if->sk_ring_seg, 1, &sc_if->sk_ring_nseg, 1236 1.63 jdolecek BUS_DMA_NOWAIT)) { 1237 1.1 riz aprint_error(": can't alloc rx buffers\n"); 1238 1.1 riz goto fail; 1239 1.1 riz } 1240 1.63 jdolecek if (bus_dmamem_map(sc->sc_dmatag, &sc_if->sk_ring_seg, 1241 1.63 jdolecek sc_if->sk_ring_nseg, 1242 1.118 jmcneill sizeof(struct msk_ring_data), &kva, 1243 1.118 jmcneill BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) { 1244 1.1 riz aprint_error(": can't map dma buffers (%zu bytes)\n", 1245 1.1 riz sizeof(struct msk_ring_data)); 1246 1.1 riz goto fail_1; 1247 1.1 riz } 1248 1.1 riz if (bus_dmamap_create(sc->sc_dmatag, sizeof(struct msk_ring_data), 1, 1249 1.1 riz sizeof(struct msk_ring_data), 0, BUS_DMA_NOWAIT, 1250 1.59 jdolecek &sc_if->sk_ring_map)) { 1251 1.1 riz aprint_error(": can't create dma map\n"); 1252 1.1 riz goto fail_2; 1253 1.1 riz } 1254 1.1 riz if (bus_dmamap_load(sc->sc_dmatag, sc_if->sk_ring_map, kva, 1255 1.1 riz sizeof(struct msk_ring_data), NULL, BUS_DMA_NOWAIT)) { 1256 1.1 riz aprint_error(": can't load dma map\n"); 1257 1.1 riz goto fail_3; 1258 1.1 riz } 1259 1.99 jakllsch 1260 1.99 jakllsch for (i = 0; i < MSK_TX_RING_CNT; i++) { 1261 1.99 jakllsch sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf = NULL; 1262 1.99 jakllsch 1263 1.99 jakllsch if (bus_dmamap_create(sc->sc_dmatag, SK_JLEN, SK_NTXSEG, 1264 1.99 jakllsch SK_JLEN, 0, BUS_DMA_NOWAIT, &dmamap)) { 1265 1.99 jakllsch aprint_error_dev(sc_if->sk_dev, 1266 1.99 jakllsch "Can't create TX dmamap\n"); 1267 1.99 jakllsch goto fail_3; 1268 1.99 jakllsch } 1269 1.99 jakllsch 1270 1.105 jakllsch sc_if->sk_cdata.sk_tx_chain[i].sk_dmamap = dmamap; 1271 1.99 jakllsch } 1272 1.99 jakllsch 1273 1.106 jakllsch for (i = 0; i < MSK_RX_RING_CNT; i++) { 1274 1.106 jakllsch sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf = NULL; 1275 1.106 jakllsch 1276 1.106 jakllsch if (bus_dmamap_create(sc->sc_dmatag, SK_JLEN, 1277 1.106 jakllsch howmany(SK_JLEN + 1, NBPG), 1278 1.106 jakllsch SK_JLEN, 0, BUS_DMA_NOWAIT, &dmamap)) { 1279 1.106 jakllsch aprint_error_dev(sc_if->sk_dev, 1280 1.106 jakllsch "Can't create RX dmamap\n"); 1281 1.106 jakllsch goto fail_3; 1282 1.106 jakllsch } 1283 1.106 jakllsch 1284 1.106 jakllsch sc_if->sk_cdata.sk_rx_chain[i].sk_dmamap = dmamap; 1285 1.106 jakllsch } 1286 1.106 jakllsch 1287 1.59 jdolecek sc_if->sk_rdata = (struct msk_ring_data *)kva; 1288 1.24 cegger memset(sc_if->sk_rdata, 0, sizeof(struct msk_ring_data)); 1289 1.1 riz 1290 1.68 jdolecek if (sc->sk_type != SK_YUKON_FE && 1291 1.68 jdolecek sc->sk_type != SK_YUKON_FE_P) 1292 1.68 jdolecek sc_if->sk_pktlen = SK_JLEN; 1293 1.68 jdolecek else 1294 1.68 jdolecek sc_if->sk_pktlen = MCLBYTES; 1295 1.68 jdolecek 1296 1.1 riz /* Try to allocate memory for jumbo buffers. */ 1297 1.1 riz if (msk_alloc_jumbo_mem(sc_if)) { 1298 1.1 riz aprint_error(": jumbo buffer allocation failed\n"); 1299 1.1 riz goto fail_3; 1300 1.1 riz } 1301 1.68 jdolecek 1302 1.19 dyoung sc_if->sk_ethercom.ec_capabilities = ETHERCAP_VLAN_MTU; 1303 1.68 jdolecek if (sc->sk_type != SK_YUKON_FE && 1304 1.68 jdolecek sc->sk_type != SK_YUKON_FE_P) 1305 1.19 dyoung sc_if->sk_ethercom.ec_capabilities |= ETHERCAP_JUMBO_MTU; 1306 1.1 riz 1307 1.68 jdolecek ifp = &sc_if->sk_ethercom.ec_if; 1308 1.1 riz ifp->if_softc = sc_if; 1309 1.1 riz ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 1310 1.1 riz ifp->if_ioctl = msk_ioctl; 1311 1.1 riz ifp->if_start = msk_start; 1312 1.1 riz ifp->if_stop = msk_stop; 1313 1.1 riz ifp->if_init = msk_init; 1314 1.1 riz ifp->if_watchdog = msk_watchdog; 1315 1.1 riz ifp->if_baudrate = 1000000000; 1316 1.1 riz IFQ_SET_MAXLEN(&ifp->if_snd, MSK_TX_RING_CNT - 1); 1317 1.1 riz IFQ_SET_READY(&ifp->if_snd); 1318 1.30 christos strlcpy(ifp->if_xname, device_xname(sc_if->sk_dev), IFNAMSIZ); 1319 1.1 riz 1320 1.63 jdolecek msk_reset(sc_if); 1321 1.63 jdolecek 1322 1.1 riz /* 1323 1.1 riz * Do miibus setup. 1324 1.1 riz */ 1325 1.89 msaitoh DPRINTFN(2, ("msk_attach: 1\n")); 1326 1.1 riz 1327 1.88 msaitoh mii->mii_ifp = ifp; 1328 1.88 msaitoh mii->mii_readreg = msk_miibus_readreg; 1329 1.88 msaitoh mii->mii_writereg = msk_miibus_writereg; 1330 1.88 msaitoh mii->mii_statchg = msk_miibus_statchg; 1331 1.88 msaitoh 1332 1.88 msaitoh sc_if->sk_ethercom.ec_mii = mii; 1333 1.88 msaitoh ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus); 1334 1.63 jdolecek mii_flags = MIIF_DOPAUSE; 1335 1.63 jdolecek if (sc->sk_fibertype) 1336 1.63 jdolecek mii_flags |= MIIF_HAVEFIBER; 1337 1.88 msaitoh mii_attach(self, mii, 0xffffffff, 0, MII_OFFSET_ANY, mii_flags); 1338 1.88 msaitoh if (LIST_FIRST(&mii->mii_phys) == NULL) { 1339 1.30 christos aprint_error_dev(sc_if->sk_dev, "no PHY found!\n"); 1340 1.88 msaitoh ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_MANUAL, 1341 1.1 riz 0, NULL); 1342 1.88 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_MANUAL); 1343 1.1 riz } else 1344 1.88 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 1345 1.1 riz 1346 1.9 ad callout_init(&sc_if->sk_tick_ch, 0); 1347 1.5 msaitoh callout_setfunc(&sc_if->sk_tick_ch, msk_tick, sc_if); 1348 1.1 riz callout_schedule(&sc_if->sk_tick_ch, hz); 1349 1.1 riz 1350 1.72 jdolecek callout_init(&sc_if->sk_tick_rx, 0); 1351 1.72 jdolecek callout_setfunc(&sc_if->sk_tick_rx, msk_fill_rx_tick, sc_if); 1352 1.72 jdolecek 1353 1.1 riz /* 1354 1.1 riz * Call MI attach routines. 1355 1.1 riz */ 1356 1.1 riz if_attach(ifp); 1357 1.53 ozaki if_deferred_start_init(ifp, NULL); 1358 1.1 riz ether_ifattach(ifp, sc_if->sk_enaddr); 1359 1.1 riz 1360 1.28 tsutsui if (pmf_device_register(self, NULL, msk_resume)) 1361 1.28 tsutsui pmf_class_network_register(self, ifp); 1362 1.28 tsutsui else 1363 1.20 joerg aprint_error_dev(self, "couldn't establish power handler\n"); 1364 1.1 riz 1365 1.69 jdolecek if (sc->rnd_attached++ == 0) { 1366 1.69 jdolecek rnd_attach_source(&sc->rnd_source, device_xname(sc->sk_dev), 1367 1.69 jdolecek RND_TYPE_NET, RND_FLAG_DEFAULT); 1368 1.69 jdolecek } 1369 1.1 riz 1370 1.1 riz DPRINTFN(2, ("msk_attach: end\n")); 1371 1.1 riz return; 1372 1.1 riz 1373 1.1 riz fail_3: 1374 1.1 riz bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map); 1375 1.1 riz fail_2: 1376 1.1 riz bus_dmamem_unmap(sc->sc_dmatag, kva, sizeof(struct msk_ring_data)); 1377 1.1 riz fail_1: 1378 1.63 jdolecek bus_dmamem_free(sc->sc_dmatag, &sc_if->sk_ring_seg, sc_if->sk_ring_nseg); 1379 1.1 riz fail: 1380 1.1 riz sc->sk_if[sa->skc_port] = NULL; 1381 1.1 riz } 1382 1.1 riz 1383 1.95 maxv static int 1384 1.63 jdolecek msk_detach(device_t self, int flags) 1385 1.63 jdolecek { 1386 1.70 jdolecek struct sk_if_softc *sc_if = device_private(self); 1387 1.63 jdolecek struct sk_softc *sc = sc_if->sk_softc; 1388 1.63 jdolecek struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; 1389 1.105 jakllsch int i; 1390 1.63 jdolecek 1391 1.63 jdolecek if (sc->sk_if[sc_if->sk_port] == NULL) 1392 1.88 msaitoh return 0; 1393 1.63 jdolecek 1394 1.81 bouyer msk_stop(ifp, 1); 1395 1.68 jdolecek 1396 1.105 jakllsch for (i = 0; i < MSK_TX_RING_CNT; i++) { 1397 1.105 jakllsch bus_dmamap_destroy(sc->sc_dmatag, 1398 1.105 jakllsch sc_if->sk_cdata.sk_tx_chain[i].sk_dmamap); 1399 1.99 jakllsch } 1400 1.99 jakllsch 1401 1.106 jakllsch for (i = 0; i < MSK_RX_RING_CNT; i++) { 1402 1.106 jakllsch bus_dmamap_destroy(sc->sc_dmatag, 1403 1.106 jakllsch sc_if->sk_cdata.sk_rx_chain[i].sk_dmamap); 1404 1.106 jakllsch } 1405 1.106 jakllsch 1406 1.69 jdolecek if (--sc->rnd_attached == 0) 1407 1.69 jdolecek rnd_detach_source(&sc->rnd_source); 1408 1.63 jdolecek 1409 1.63 jdolecek callout_halt(&sc_if->sk_tick_ch, NULL); 1410 1.63 jdolecek callout_destroy(&sc_if->sk_tick_ch); 1411 1.63 jdolecek 1412 1.72 jdolecek callout_halt(&sc_if->sk_tick_rx, NULL); 1413 1.72 jdolecek callout_destroy(&sc_if->sk_tick_rx); 1414 1.72 jdolecek 1415 1.63 jdolecek /* Detach any PHYs we might have. */ 1416 1.63 jdolecek if (LIST_FIRST(&sc_if->sk_mii.mii_phys) != NULL) 1417 1.63 jdolecek mii_detach(&sc_if->sk_mii, MII_PHY_ANY, MII_OFFSET_ANY); 1418 1.63 jdolecek 1419 1.63 jdolecek pmf_device_deregister(self); 1420 1.63 jdolecek 1421 1.63 jdolecek ether_ifdetach(ifp); 1422 1.63 jdolecek if_detach(ifp); 1423 1.63 jdolecek 1424 1.98 thorpej /* Delete any remaining media. */ 1425 1.98 thorpej ifmedia_fini(&sc_if->sk_mii.mii_media); 1426 1.98 thorpej 1427 1.70 jdolecek msk_free_jumbo_mem(sc_if); 1428 1.70 jdolecek 1429 1.63 jdolecek bus_dmamem_unmap(sc->sc_dmatag, sc_if->sk_rdata, 1430 1.63 jdolecek sizeof(struct msk_ring_data)); 1431 1.63 jdolecek bus_dmamem_free(sc->sc_dmatag, 1432 1.63 jdolecek &sc_if->sk_ring_seg, sc_if->sk_ring_nseg); 1433 1.68 jdolecek bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map); 1434 1.63 jdolecek sc->sk_if[sc_if->sk_port] = NULL; 1435 1.63 jdolecek 1436 1.88 msaitoh return 0; 1437 1.63 jdolecek } 1438 1.63 jdolecek 1439 1.95 maxv static int 1440 1.1 riz mskcprint(void *aux, const char *pnp) 1441 1.1 riz { 1442 1.1 riz struct skc_attach_args *sa = aux; 1443 1.1 riz 1444 1.1 riz if (pnp) 1445 1.64 jdolecek aprint_normal("msk port %c at %s", 1446 1.1 riz (sa->skc_port == SK_PORT_A) ? 'A' : 'B', pnp); 1447 1.1 riz else 1448 1.83 msaitoh aprint_normal(" port %c", 1449 1.83 msaitoh (sa->skc_port == SK_PORT_A) ? 'A' : 'B'); 1450 1.88 msaitoh return UNCONF; 1451 1.1 riz } 1452 1.1 riz 1453 1.1 riz /* 1454 1.1 riz * Attach the interface. Allocate softc structures, do ifmedia 1455 1.1 riz * setup and ethernet/BPF attach. 1456 1.1 riz */ 1457 1.95 maxv static void 1458 1.26 cegger mskc_attach(device_t parent, device_t self, void *aux) 1459 1.1 riz { 1460 1.27 cegger struct sk_softc *sc = device_private(self); 1461 1.1 riz struct pci_attach_args *pa = aux; 1462 1.1 riz struct skc_attach_args skca; 1463 1.1 riz pci_chipset_tag_t pc = pa->pa_pc; 1464 1.1 riz pcireg_t command, memtype; 1465 1.1 riz const char *intrstr = NULL; 1466 1.1 riz int rc, sk_nodenum; 1467 1.83 msaitoh uint8_t hw, pmd; 1468 1.1 riz const char *revstr = NULL; 1469 1.1 riz const struct sysctlnode *node; 1470 1.8 christos void *kva; 1471 1.45 christos char intrbuf[PCI_INTRSTR_LEN]; 1472 1.1 riz 1473 1.1 riz DPRINTFN(2, ("begin mskc_attach\n")); 1474 1.1 riz 1475 1.30 christos sc->sk_dev = self; 1476 1.1 riz /* 1477 1.1 riz * Handle power management nonsense. 1478 1.1 riz */ 1479 1.1 riz command = pci_conf_read(pc, pa->pa_tag, SK_PCI_CAPID) & 0x000000FF; 1480 1.1 riz 1481 1.1 riz if (command == 0x01) { 1482 1.1 riz command = pci_conf_read(pc, pa->pa_tag, SK_PCI_PWRMGMTCTRL); 1483 1.1 riz if (command & SK_PSTATE_MASK) { 1484 1.83 msaitoh uint32_t iobase, membase, irq; 1485 1.1 riz 1486 1.1 riz /* Save important PCI config data. */ 1487 1.1 riz iobase = pci_conf_read(pc, pa->pa_tag, SK_PCI_LOIO); 1488 1.1 riz membase = pci_conf_read(pc, pa->pa_tag, SK_PCI_LOMEM); 1489 1.1 riz irq = pci_conf_read(pc, pa->pa_tag, SK_PCI_INTLINE); 1490 1.1 riz 1491 1.1 riz /* Reset the power state. */ 1492 1.30 christos aprint_normal_dev(sc->sk_dev, "chip is in D%d power " 1493 1.30 christos "mode -- setting to D0\n", 1494 1.1 riz command & SK_PSTATE_MASK); 1495 1.1 riz command &= 0xFFFFFFFC; 1496 1.1 riz pci_conf_write(pc, pa->pa_tag, 1497 1.1 riz SK_PCI_PWRMGMTCTRL, command); 1498 1.1 riz 1499 1.1 riz /* Restore PCI config data. */ 1500 1.1 riz pci_conf_write(pc, pa->pa_tag, SK_PCI_LOIO, iobase); 1501 1.1 riz pci_conf_write(pc, pa->pa_tag, SK_PCI_LOMEM, membase); 1502 1.1 riz pci_conf_write(pc, pa->pa_tag, SK_PCI_INTLINE, irq); 1503 1.1 riz } 1504 1.1 riz } 1505 1.1 riz 1506 1.1 riz /* 1507 1.1 riz * Map control/status registers. 1508 1.1 riz */ 1509 1.1 riz memtype = pci_mapreg_type(pc, pa->pa_tag, SK_PCI_LOMEM); 1510 1.63 jdolecek if (pci_mapreg_map(pa, SK_PCI_LOMEM, memtype, 0, &sc->sk_btag, 1511 1.77 jakllsch &sc->sk_bhandle, NULL, &sc->sk_bsize)) { 1512 1.1 riz aprint_error(": can't map mem space\n"); 1513 1.1 riz return; 1514 1.1 riz } 1515 1.1 riz 1516 1.78 jakllsch if (pci_dma64_available(pa)) 1517 1.78 jakllsch sc->sc_dmatag = pa->pa_dmat64; 1518 1.78 jakllsch else 1519 1.78 jakllsch sc->sc_dmatag = pa->pa_dmat; 1520 1.1 riz 1521 1.36 jakllsch command = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 1522 1.37 jakllsch command |= PCI_COMMAND_MASTER_ENABLE; 1523 1.36 jakllsch pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); 1524 1.36 jakllsch 1525 1.1 riz sc->sk_type = sk_win_read_1(sc, SK_CHIPVER); 1526 1.1 riz sc->sk_rev = (sk_win_read_1(sc, SK_CONFIG) >> 4); 1527 1.1 riz 1528 1.1 riz /* bail out here if chip is not recognized */ 1529 1.5 msaitoh if (!(SK_IS_YUKON2(sc))) { 1530 1.1 riz aprint_error(": unknown chip type: %d\n", sc->sk_type); 1531 1.1 riz goto fail_1; 1532 1.1 riz } 1533 1.1 riz DPRINTFN(2, ("mskc_attach: allocate interrupt\n")); 1534 1.1 riz 1535 1.1 riz /* Allocate interrupt */ 1536 1.79 jmcneill if (pci_intr_alloc(pa, &sc->sk_pihp, NULL, 0)) { 1537 1.1 riz aprint_error(": couldn't map interrupt\n"); 1538 1.1 riz goto fail_1; 1539 1.1 riz } 1540 1.1 riz 1541 1.79 jmcneill intrstr = pci_intr_string(pc, sc->sk_pihp[0], intrbuf, sizeof(intrbuf)); 1542 1.80 jdolecek sc->sk_intrhand = pci_intr_establish_xname(pc, sc->sk_pihp[0], IPL_NET, 1543 1.80 jdolecek msk_intr, sc, device_xname(sc->sk_dev)); 1544 1.1 riz if (sc->sk_intrhand == NULL) { 1545 1.1 riz aprint_error(": couldn't establish interrupt"); 1546 1.1 riz if (intrstr != NULL) 1547 1.1 riz aprint_error(" at %s", intrstr); 1548 1.1 riz aprint_error("\n"); 1549 1.1 riz goto fail_1; 1550 1.1 riz } 1551 1.63 jdolecek sc->sk_pc = pc; 1552 1.1 riz 1553 1.1 riz if (bus_dmamem_alloc(sc->sc_dmatag, 1554 1.68 jdolecek MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), 1555 1.68 jdolecek MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), 1556 1.63 jdolecek 0, &sc->sk_status_seg, 1, &sc->sk_status_nseg, BUS_DMA_NOWAIT)) { 1557 1.1 riz aprint_error(": can't alloc status buffers\n"); 1558 1.1 riz goto fail_2; 1559 1.1 riz } 1560 1.1 riz 1561 1.63 jdolecek if (bus_dmamem_map(sc->sc_dmatag, 1562 1.63 jdolecek &sc->sk_status_seg, sc->sk_status_nseg, 1563 1.1 riz MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), 1564 1.118 jmcneill &kva, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) { 1565 1.1 riz aprint_error(": can't map dma buffers (%zu bytes)\n", 1566 1.1 riz MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)); 1567 1.1 riz goto fail_3; 1568 1.1 riz } 1569 1.1 riz if (bus_dmamap_create(sc->sc_dmatag, 1570 1.1 riz MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), 1, 1571 1.1 riz MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), 0, 1572 1.1 riz BUS_DMA_NOWAIT, &sc->sk_status_map)) { 1573 1.1 riz aprint_error(": can't create dma map\n"); 1574 1.1 riz goto fail_4; 1575 1.1 riz } 1576 1.1 riz if (bus_dmamap_load(sc->sc_dmatag, sc->sk_status_map, kva, 1577 1.1 riz MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), 1578 1.1 riz NULL, BUS_DMA_NOWAIT)) { 1579 1.1 riz aprint_error(": can't load dma map\n"); 1580 1.1 riz goto fail_5; 1581 1.1 riz } 1582 1.1 riz sc->sk_status_ring = (struct msk_status_desc *)kva; 1583 1.1 riz 1584 1.30 christos sc->sk_int_mod = SK_IM_DEFAULT; 1585 1.30 christos sc->sk_int_mod_pending = 0; 1586 1.30 christos 1587 1.1 riz /* Reset the adapter. */ 1588 1.63 jdolecek mskc_reset(sc); 1589 1.1 riz 1590 1.57 jdolecek sc->sk_ramsize = sk_win_read_1(sc, SK_EPROM0) * 4096; 1591 1.57 jdolecek DPRINTFN(2, ("mskc_attach: ramsize=%dK\n", sc->sk_ramsize / 1024)); 1592 1.1 riz 1593 1.63 jdolecek pmd = sk_win_read_1(sc, SK_PMDTYPE); 1594 1.63 jdolecek if (pmd == 'L' || pmd == 'S' || pmd == 'P') 1595 1.63 jdolecek sc->sk_fibertype = 1; 1596 1.63 jdolecek 1597 1.1 riz switch (sc->sk_type) { 1598 1.1 riz case SK_YUKON_XL: 1599 1.5 msaitoh sc->sk_name = "Yukon-2 XL"; 1600 1.1 riz break; 1601 1.1 riz case SK_YUKON_EC_U: 1602 1.5 msaitoh sc->sk_name = "Yukon-2 EC Ultra"; 1603 1.1 riz break; 1604 1.56 jdolecek case SK_YUKON_EX: 1605 1.56 jdolecek sc->sk_name = "Yukon-2 Extreme"; 1606 1.56 jdolecek break; 1607 1.1 riz case SK_YUKON_EC: 1608 1.5 msaitoh sc->sk_name = "Yukon-2 EC"; 1609 1.1 riz break; 1610 1.1 riz case SK_YUKON_FE: 1611 1.5 msaitoh sc->sk_name = "Yukon-2 FE"; 1612 1.1 riz break; 1613 1.56 jdolecek case SK_YUKON_FE_P: 1614 1.56 jdolecek sc->sk_name = "Yukon-2 FE+"; 1615 1.56 jdolecek break; 1616 1.56 jdolecek case SK_YUKON_SUPR: 1617 1.56 jdolecek sc->sk_name = "Yukon-2 Supreme"; 1618 1.56 jdolecek break; 1619 1.56 jdolecek case SK_YUKON_ULTRA2: 1620 1.56 jdolecek sc->sk_name = "Yukon-2 Ultra 2"; 1621 1.56 jdolecek break; 1622 1.56 jdolecek case SK_YUKON_OPTIMA: 1623 1.56 jdolecek sc->sk_name = "Yukon-2 Optima"; 1624 1.56 jdolecek break; 1625 1.56 jdolecek case SK_YUKON_PRM: 1626 1.56 jdolecek sc->sk_name = "Yukon-2 Optima Prime"; 1627 1.56 jdolecek break; 1628 1.56 jdolecek case SK_YUKON_OPTIMA2: 1629 1.56 jdolecek sc->sk_name = "Yukon-2 Optima 2"; 1630 1.56 jdolecek break; 1631 1.1 riz default: 1632 1.5 msaitoh sc->sk_name = "Yukon (Unknown)"; 1633 1.1 riz } 1634 1.1 riz 1635 1.1 riz if (sc->sk_type == SK_YUKON_XL) { 1636 1.1 riz switch (sc->sk_rev) { 1637 1.1 riz case SK_YUKON_XL_REV_A0: 1638 1.1 riz revstr = "A0"; 1639 1.1 riz break; 1640 1.1 riz case SK_YUKON_XL_REV_A1: 1641 1.1 riz revstr = "A1"; 1642 1.1 riz break; 1643 1.1 riz case SK_YUKON_XL_REV_A2: 1644 1.1 riz revstr = "A2"; 1645 1.1 riz break; 1646 1.1 riz case SK_YUKON_XL_REV_A3: 1647 1.1 riz revstr = "A3"; 1648 1.1 riz break; 1649 1.1 riz default: 1650 1.6 msaitoh break; 1651 1.1 riz } 1652 1.1 riz } 1653 1.1 riz 1654 1.1 riz if (sc->sk_type == SK_YUKON_EC) { 1655 1.1 riz switch (sc->sk_rev) { 1656 1.1 riz case SK_YUKON_EC_REV_A1: 1657 1.1 riz revstr = "A1"; 1658 1.1 riz break; 1659 1.1 riz case SK_YUKON_EC_REV_A2: 1660 1.1 riz revstr = "A2"; 1661 1.1 riz break; 1662 1.1 riz case SK_YUKON_EC_REV_A3: 1663 1.1 riz revstr = "A3"; 1664 1.1 riz break; 1665 1.1 riz default: 1666 1.6 msaitoh break; 1667 1.6 msaitoh } 1668 1.6 msaitoh } 1669 1.6 msaitoh 1670 1.6 msaitoh if (sc->sk_type == SK_YUKON_FE) { 1671 1.6 msaitoh switch (sc->sk_rev) { 1672 1.6 msaitoh case SK_YUKON_FE_REV_A1: 1673 1.6 msaitoh revstr = "A1"; 1674 1.6 msaitoh break; 1675 1.6 msaitoh case SK_YUKON_FE_REV_A2: 1676 1.6 msaitoh revstr = "A2"; 1677 1.6 msaitoh break; 1678 1.6 msaitoh default: 1679 1.6 msaitoh break; 1680 1.1 riz } 1681 1.1 riz } 1682 1.1 riz 1683 1.1 riz if (sc->sk_type == SK_YUKON_EC_U) { 1684 1.1 riz switch (sc->sk_rev) { 1685 1.1 riz case SK_YUKON_EC_U_REV_A0: 1686 1.1 riz revstr = "A0"; 1687 1.1 riz break; 1688 1.1 riz case SK_YUKON_EC_U_REV_A1: 1689 1.1 riz revstr = "A1"; 1690 1.1 riz break; 1691 1.6 msaitoh case SK_YUKON_EC_U_REV_B0: 1692 1.6 msaitoh revstr = "B0"; 1693 1.6 msaitoh break; 1694 1.56 jdolecek case SK_YUKON_EC_U_REV_B1: 1695 1.56 jdolecek revstr = "B1"; 1696 1.56 jdolecek break; 1697 1.1 riz default: 1698 1.6 msaitoh break; 1699 1.1 riz } 1700 1.1 riz } 1701 1.1 riz 1702 1.56 jdolecek if (sc->sk_type == SK_YUKON_FE) { 1703 1.56 jdolecek switch (sc->sk_rev) { 1704 1.56 jdolecek case SK_YUKON_FE_REV_A1: 1705 1.56 jdolecek revstr = "A1"; 1706 1.56 jdolecek break; 1707 1.56 jdolecek case SK_YUKON_FE_REV_A2: 1708 1.56 jdolecek revstr = "A2"; 1709 1.56 jdolecek break; 1710 1.56 jdolecek default: 1711 1.56 jdolecek ; 1712 1.56 jdolecek } 1713 1.56 jdolecek } 1714 1.56 jdolecek 1715 1.56 jdolecek if (sc->sk_type == SK_YUKON_FE_P && sc->sk_rev == SK_YUKON_FE_P_REV_A0) 1716 1.56 jdolecek revstr = "A0"; 1717 1.56 jdolecek 1718 1.56 jdolecek if (sc->sk_type == SK_YUKON_EX) { 1719 1.56 jdolecek switch (sc->sk_rev) { 1720 1.56 jdolecek case SK_YUKON_EX_REV_A0: 1721 1.56 jdolecek revstr = "A0"; 1722 1.56 jdolecek break; 1723 1.56 jdolecek case SK_YUKON_EX_REV_B0: 1724 1.56 jdolecek revstr = "B0"; 1725 1.56 jdolecek break; 1726 1.56 jdolecek default: 1727 1.56 jdolecek ; 1728 1.56 jdolecek } 1729 1.56 jdolecek } 1730 1.56 jdolecek 1731 1.56 jdolecek if (sc->sk_type == SK_YUKON_SUPR) { 1732 1.56 jdolecek switch (sc->sk_rev) { 1733 1.56 jdolecek case SK_YUKON_SUPR_REV_A0: 1734 1.56 jdolecek revstr = "A0"; 1735 1.56 jdolecek break; 1736 1.56 jdolecek case SK_YUKON_SUPR_REV_B0: 1737 1.56 jdolecek revstr = "B0"; 1738 1.56 jdolecek break; 1739 1.56 jdolecek case SK_YUKON_SUPR_REV_B1: 1740 1.56 jdolecek revstr = "B1"; 1741 1.56 jdolecek break; 1742 1.56 jdolecek default: 1743 1.56 jdolecek ; 1744 1.56 jdolecek } 1745 1.56 jdolecek } 1746 1.56 jdolecek 1747 1.56 jdolecek if (sc->sk_type == SK_YUKON_PRM) { 1748 1.56 jdolecek switch (sc->sk_rev) { 1749 1.56 jdolecek case SK_YUKON_PRM_REV_Z1: 1750 1.56 jdolecek revstr = "Z1"; 1751 1.56 jdolecek break; 1752 1.56 jdolecek case SK_YUKON_PRM_REV_A0: 1753 1.56 jdolecek revstr = "A0"; 1754 1.56 jdolecek break; 1755 1.56 jdolecek default: 1756 1.56 jdolecek ; 1757 1.56 jdolecek } 1758 1.56 jdolecek } 1759 1.56 jdolecek 1760 1.1 riz /* Announce the product name. */ 1761 1.1 riz aprint_normal(", %s", sc->sk_name); 1762 1.1 riz if (revstr != NULL) 1763 1.1 riz aprint_normal(" rev. %s", revstr); 1764 1.107 jakllsch aprint_normal(" (0x%x)\n", sc->sk_rev); 1765 1.1 riz 1766 1.100 jdolecek aprint_normal_dev(sc->sk_dev, "interrupting at %s\n", intrstr); 1767 1.100 jdolecek 1768 1.1 riz sc->sk_macs = 1; 1769 1.1 riz 1770 1.1 riz hw = sk_win_read_1(sc, SK_Y2_HWRES); 1771 1.1 riz if ((hw & SK_Y2_HWRES_LINK_MASK) == SK_Y2_HWRES_LINK_DUAL) { 1772 1.1 riz if ((sk_win_read_1(sc, SK_Y2_CLKGATE) & 1773 1.1 riz SK_Y2_CLKGATE_LINK2_INACTIVE) == 0) 1774 1.1 riz sc->sk_macs++; 1775 1.1 riz } 1776 1.1 riz 1777 1.1 riz skca.skc_port = SK_PORT_A; 1778 1.1 riz skca.skc_type = sc->sk_type; 1779 1.1 riz skca.skc_rev = sc->sk_rev; 1780 1.117 thorpej (void)config_found(sc->sk_dev, &skca, mskcprint, CFARGS_NONE); 1781 1.1 riz 1782 1.1 riz if (sc->sk_macs > 1) { 1783 1.1 riz skca.skc_port = SK_PORT_B; 1784 1.1 riz skca.skc_type = sc->sk_type; 1785 1.1 riz skca.skc_rev = sc->sk_rev; 1786 1.117 thorpej (void)config_found(sc->sk_dev, &skca, mskcprint, CFARGS_NONE); 1787 1.1 riz } 1788 1.1 riz 1789 1.1 riz /* Turn on the 'driver is loaded' LED. */ 1790 1.1 riz CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_ON); 1791 1.1 riz 1792 1.1 riz /* skc sysctl setup */ 1793 1.1 riz 1794 1.1 riz if ((rc = sysctl_createv(&sc->sk_clog, 0, NULL, &node, 1795 1.30 christos 0, CTLTYPE_NODE, device_xname(sc->sk_dev), 1796 1.1 riz SYSCTL_DESCR("mskc per-controller controls"), 1797 1.1 riz NULL, 0, NULL, 0, CTL_HW, msk_root_num, CTL_CREATE, 1798 1.1 riz CTL_EOL)) != 0) { 1799 1.30 christos aprint_normal_dev(sc->sk_dev, "couldn't create sysctl node\n"); 1800 1.1 riz goto fail_6; 1801 1.1 riz } 1802 1.1 riz 1803 1.1 riz sk_nodenum = node->sysctl_num; 1804 1.1 riz 1805 1.1 riz /* interrupt moderation time in usecs */ 1806 1.1 riz if ((rc = sysctl_createv(&sc->sk_clog, 0, NULL, &node, 1807 1.1 riz CTLFLAG_READWRITE, 1808 1.1 riz CTLTYPE_INT, "int_mod", 1809 1.1 riz SYSCTL_DESCR("msk interrupt moderation timer"), 1810 1.40 dsl msk_sysctl_handler, 0, (void *)sc, 1811 1.1 riz 0, CTL_HW, msk_root_num, sk_nodenum, CTL_CREATE, 1812 1.1 riz CTL_EOL)) != 0) { 1813 1.83 msaitoh aprint_normal_dev(sc->sk_dev, 1814 1.83 msaitoh "couldn't create int_mod sysctl node\n"); 1815 1.1 riz goto fail_6; 1816 1.1 riz } 1817 1.1 riz 1818 1.20 joerg if (!pmf_device_register(self, mskc_suspend, mskc_resume)) 1819 1.20 joerg aprint_error_dev(self, "couldn't establish power handler\n"); 1820 1.20 joerg 1821 1.1 riz return; 1822 1.1 riz 1823 1.68 jdolecek fail_6: 1824 1.1 riz bus_dmamap_unload(sc->sc_dmatag, sc->sk_status_map); 1825 1.1 riz fail_4: 1826 1.43 christos bus_dmamem_unmap(sc->sc_dmatag, kva, 1827 1.1 riz MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)); 1828 1.1 riz fail_3: 1829 1.63 jdolecek bus_dmamem_free(sc->sc_dmatag, 1830 1.63 jdolecek &sc->sk_status_seg, sc->sk_status_nseg); 1831 1.63 jdolecek sc->sk_status_nseg = 0; 1832 1.68 jdolecek fail_5: 1833 1.68 jdolecek bus_dmamap_destroy(sc->sc_dmatag, sc->sk_status_map); 1834 1.1 riz fail_2: 1835 1.1 riz pci_intr_disestablish(pc, sc->sk_intrhand); 1836 1.63 jdolecek sc->sk_intrhand = NULL; 1837 1.1 riz fail_1: 1838 1.77 jakllsch bus_space_unmap(sc->sk_btag, sc->sk_bhandle, sc->sk_bsize); 1839 1.63 jdolecek sc->sk_bsize = 0; 1840 1.63 jdolecek } 1841 1.63 jdolecek 1842 1.95 maxv static int 1843 1.63 jdolecek mskc_detach(device_t self, int flags) 1844 1.63 jdolecek { 1845 1.70 jdolecek struct sk_softc *sc = device_private(self); 1846 1.63 jdolecek int rv; 1847 1.63 jdolecek 1848 1.77 jakllsch if (sc->sk_intrhand) { 1849 1.68 jdolecek pci_intr_disestablish(sc->sk_pc, sc->sk_intrhand); 1850 1.77 jakllsch sc->sk_intrhand = NULL; 1851 1.77 jakllsch } 1852 1.68 jdolecek 1853 1.79 jmcneill if (sc->sk_pihp != NULL) { 1854 1.79 jmcneill pci_intr_release(sc->sk_pc, sc->sk_pihp, 1); 1855 1.79 jmcneill sc->sk_pihp = NULL; 1856 1.79 jmcneill } 1857 1.79 jmcneill 1858 1.63 jdolecek rv = config_detach_children(self, flags); 1859 1.63 jdolecek if (rv != 0) 1860 1.88 msaitoh return rv; 1861 1.63 jdolecek 1862 1.110 jakllsch sysctl_teardown(&sc->sk_clog); 1863 1.110 jakllsch 1864 1.63 jdolecek if (sc->sk_status_nseg > 0) { 1865 1.63 jdolecek bus_dmamap_destroy(sc->sc_dmatag, sc->sk_status_map); 1866 1.63 jdolecek bus_dmamem_unmap(sc->sc_dmatag, sc->sk_status_ring, 1867 1.63 jdolecek MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)); 1868 1.63 jdolecek bus_dmamem_free(sc->sc_dmatag, 1869 1.63 jdolecek &sc->sk_status_seg, sc->sk_status_nseg); 1870 1.63 jdolecek } 1871 1.63 jdolecek 1872 1.63 jdolecek if (sc->sk_bsize > 0) 1873 1.63 jdolecek bus_space_unmap(sc->sk_btag, sc->sk_bhandle, sc->sk_bsize); 1874 1.63 jdolecek 1875 1.88 msaitoh return 0; 1876 1.1 riz } 1877 1.1 riz 1878 1.95 maxv static int 1879 1.83 msaitoh msk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, uint32_t *txidx) 1880 1.1 riz { 1881 1.1 riz struct sk_softc *sc = sc_if->sk_softc; 1882 1.1 riz struct msk_tx_desc *f = NULL; 1883 1.109 jakllsch uint32_t frag, cur, hiaddr, total; 1884 1.83 msaitoh uint32_t entries = 0; 1885 1.109 jakllsch uint8_t own = 0; 1886 1.78 jakllsch size_t i; 1887 1.1 riz bus_dmamap_t txmap; 1888 1.78 jakllsch bus_addr_t addr; 1889 1.1 riz 1890 1.1 riz DPRINTFN(2, ("msk_encap\n")); 1891 1.1 riz 1892 1.105 jakllsch txmap = sc_if->sk_cdata.sk_tx_chain[*txidx].sk_dmamap; 1893 1.1 riz 1894 1.1 riz cur = frag = *txidx; 1895 1.1 riz 1896 1.1 riz #ifdef MSK_DEBUG 1897 1.1 riz if (mskdebug >= 2) 1898 1.1 riz msk_dump_mbuf(m_head); 1899 1.1 riz #endif 1900 1.1 riz 1901 1.1 riz /* 1902 1.1 riz * Start packing the mbufs in this chain into 1903 1.1 riz * the fragment pointers. Stop when we run out 1904 1.1 riz * of fragments or hit the end of the mbuf chain. 1905 1.1 riz */ 1906 1.1 riz if (bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head, 1907 1.1 riz BUS_DMA_NOWAIT)) { 1908 1.1 riz DPRINTFN(2, ("msk_encap: dmamap failed\n")); 1909 1.88 msaitoh return ENOBUFS; 1910 1.1 riz } 1911 1.1 riz 1912 1.78 jakllsch /* Count how many tx descriptors needed. */ 1913 1.78 jakllsch hiaddr = sc_if->sk_cdata.sk_tx_hiaddr; 1914 1.78 jakllsch for (total = i = 0; i < txmap->dm_nsegs; i++) { 1915 1.78 jakllsch if (hiaddr != MSK_ADDR_HI(txmap->dm_segs[i].ds_addr)) { 1916 1.78 jakllsch hiaddr = MSK_ADDR_HI(txmap->dm_segs[i].ds_addr); 1917 1.78 jakllsch total++; 1918 1.78 jakllsch } 1919 1.78 jakllsch total++; 1920 1.78 jakllsch } 1921 1.78 jakllsch 1922 1.78 jakllsch if (total > MSK_TX_RING_CNT - sc_if->sk_cdata.sk_tx_cnt - 2) { 1923 1.5 msaitoh DPRINTFN(2, ("msk_encap: too few descriptors free\n")); 1924 1.5 msaitoh bus_dmamap_unload(sc->sc_dmatag, txmap); 1925 1.88 msaitoh return ENOBUFS; 1926 1.5 msaitoh } 1927 1.5 msaitoh 1928 1.78 jakllsch DPRINTFN(2, ("msk_encap: dm_nsegs=%d total desc=%u\n", 1929 1.78 jakllsch txmap->dm_nsegs, total)); 1930 1.1 riz 1931 1.1 riz /* Sync the DMA map. */ 1932 1.1 riz bus_dmamap_sync(sc->sc_dmatag, txmap, 0, txmap->dm_mapsize, 1933 1.1 riz BUS_DMASYNC_PREWRITE); 1934 1.1 riz 1935 1.1 riz for (i = 0; i < txmap->dm_nsegs; i++) { 1936 1.78 jakllsch addr = txmap->dm_segs[i].ds_addr; 1937 1.78 jakllsch DPRINTFN(2, ("msk_encap: addr %llx\n", 1938 1.78 jakllsch (unsigned long long)addr)); 1939 1.78 jakllsch hiaddr = MSK_ADDR_HI(addr); 1940 1.78 jakllsch 1941 1.78 jakllsch if (sc_if->sk_cdata.sk_tx_hiaddr != hiaddr) { 1942 1.78 jakllsch f = &sc_if->sk_rdata->sk_tx_ring[frag]; 1943 1.78 jakllsch f->sk_addr = htole32(hiaddr); 1944 1.78 jakllsch f->sk_len = 0; 1945 1.78 jakllsch f->sk_ctl = 0; 1946 1.109 jakllsch f->sk_opcode = SK_Y2_BMUOPC_ADDR64 | own; 1947 1.109 jakllsch own = SK_Y2_TXOPC_OWN; 1948 1.78 jakllsch sc_if->sk_cdata.sk_tx_hiaddr = hiaddr; 1949 1.78 jakllsch SK_INC(frag, MSK_TX_RING_CNT); 1950 1.78 jakllsch entries++; 1951 1.78 jakllsch DPRINTFN(10, ("%s: tx ADDR64: %#x\n", 1952 1.78 jakllsch sc_if->sk_ethercom.ec_if.if_xname, hiaddr)); 1953 1.78 jakllsch } 1954 1.78 jakllsch 1955 1.1 riz f = &sc_if->sk_rdata->sk_tx_ring[frag]; 1956 1.78 jakllsch f->sk_addr = htole32(MSK_ADDR_LO(addr)); 1957 1.1 riz f->sk_len = htole16(txmap->dm_segs[i].ds_len); 1958 1.1 riz f->sk_ctl = 0; 1959 1.78 jakllsch if (i == 0) { 1960 1.109 jakllsch f->sk_opcode = SK_Y2_TXOPC_PACKET | own; 1961 1.78 jakllsch } else 1962 1.109 jakllsch f->sk_opcode = SK_Y2_TXOPC_BUFFER | own; 1963 1.109 jakllsch own = SK_Y2_TXOPC_OWN; 1964 1.1 riz cur = frag; 1965 1.1 riz SK_INC(frag, MSK_TX_RING_CNT); 1966 1.78 jakllsch entries++; 1967 1.1 riz } 1968 1.78 jakllsch KASSERTMSG(entries == total, "entries %u total %u", entries, total); 1969 1.1 riz 1970 1.105 jakllsch sc_if->sk_cdata.sk_tx_chain[*txidx].sk_dmamap = 1971 1.105 jakllsch sc_if->sk_cdata.sk_tx_chain[cur].sk_dmamap; 1972 1.1 riz sc_if->sk_cdata.sk_tx_chain[cur].sk_mbuf = m_head; 1973 1.105 jakllsch sc_if->sk_cdata.sk_tx_chain[cur].sk_dmamap = txmap; 1974 1.1 riz 1975 1.1 riz sc_if->sk_rdata->sk_tx_ring[cur].sk_ctl |= SK_Y2_TXCTL_LASTFRAG; 1976 1.1 riz 1977 1.1 riz /* Sync descriptors before handing to chip */ 1978 1.78 jakllsch MSK_CDTXSYNC(sc_if, *txidx, entries, 1979 1.88 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1980 1.1 riz 1981 1.1 riz sc_if->sk_rdata->sk_tx_ring[*txidx].sk_opcode |= SK_Y2_TXOPC_OWN; 1982 1.1 riz 1983 1.1 riz /* Sync first descriptor to hand it off */ 1984 1.1 riz MSK_CDTXSYNC(sc_if, *txidx, 1, 1985 1.88 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1986 1.1 riz 1987 1.78 jakllsch sc_if->sk_cdata.sk_tx_cnt += entries; 1988 1.1 riz 1989 1.1 riz #ifdef MSK_DEBUG 1990 1.1 riz if (mskdebug >= 2) { 1991 1.1 riz struct msk_tx_desc *le; 1992 1.83 msaitoh uint32_t idx; 1993 1.1 riz for (idx = *txidx; idx != frag; SK_INC(idx, MSK_TX_RING_CNT)) { 1994 1.1 riz le = &sc_if->sk_rdata->sk_tx_ring[idx]; 1995 1.1 riz msk_dump_txdesc(le, idx); 1996 1.1 riz } 1997 1.1 riz } 1998 1.1 riz #endif 1999 1.1 riz 2000 1.1 riz *txidx = frag; 2001 1.1 riz 2002 1.82 mrg DPRINTFN(2, ("msk_encap: successful: %u entries\n", entries)); 2003 1.1 riz 2004 1.88 msaitoh return 0; 2005 1.1 riz } 2006 1.1 riz 2007 1.95 maxv static void 2008 1.1 riz msk_start(struct ifnet *ifp) 2009 1.1 riz { 2010 1.59 jdolecek struct sk_if_softc *sc_if = ifp->if_softc; 2011 1.59 jdolecek struct mbuf *m_head = NULL; 2012 1.83 msaitoh uint32_t idx = sc_if->sk_cdata.sk_tx_prod; 2013 1.1 riz int pkts = 0; 2014 1.1 riz 2015 1.1 riz DPRINTFN(2, ("msk_start\n")); 2016 1.1 riz 2017 1.1 riz while (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf == NULL) { 2018 1.1 riz IFQ_POLL(&ifp->if_snd, m_head); 2019 1.1 riz if (m_head == NULL) 2020 1.1 riz break; 2021 1.1 riz 2022 1.1 riz /* 2023 1.1 riz * Pack the data into the transmit ring. If we 2024 1.1 riz * don't have room, set the OACTIVE flag and wait 2025 1.1 riz * for the NIC to drain the ring. 2026 1.1 riz */ 2027 1.1 riz if (msk_encap(sc_if, m_head, &idx)) { 2028 1.1 riz ifp->if_flags |= IFF_OACTIVE; 2029 1.1 riz break; 2030 1.1 riz } 2031 1.1 riz 2032 1.1 riz /* now we are committed to transmit the packet */ 2033 1.1 riz IFQ_DEQUEUE(&ifp->if_snd, m_head); 2034 1.1 riz pkts++; 2035 1.1 riz 2036 1.1 riz /* 2037 1.1 riz * If there's a BPF listener, bounce a copy of this frame 2038 1.1 riz * to him. 2039 1.1 riz */ 2040 1.67 msaitoh bpf_mtap(ifp, m_head, BPF_D_OUT); 2041 1.1 riz } 2042 1.1 riz if (pkts == 0) 2043 1.1 riz return; 2044 1.1 riz 2045 1.1 riz /* Transmit */ 2046 1.1 riz if (idx != sc_if->sk_cdata.sk_tx_prod) { 2047 1.1 riz sc_if->sk_cdata.sk_tx_prod = idx; 2048 1.1 riz SK_IF_WRITE_2(sc_if, 1, SK_TXQA1_Y2_PREF_PUTIDX, idx); 2049 1.1 riz 2050 1.1 riz /* Set a timeout in case the chip goes out to lunch. */ 2051 1.1 riz ifp->if_timer = 5; 2052 1.1 riz } 2053 1.1 riz } 2054 1.1 riz 2055 1.95 maxv static void 2056 1.1 riz msk_watchdog(struct ifnet *ifp) 2057 1.1 riz { 2058 1.1 riz struct sk_if_softc *sc_if = ifp->if_softc; 2059 1.1 riz 2060 1.1 riz /* 2061 1.1 riz * Reclaim first as there is a possibility of losing Tx completion 2062 1.1 riz * interrupts. 2063 1.1 riz */ 2064 1.68 jdolecek msk_txeof(sc_if); 2065 1.68 jdolecek if (sc_if->sk_cdata.sk_tx_cnt != 0) { 2066 1.114 jakllsch device_printf(sc_if->sk_dev, "watchdog timeout\n"); 2067 1.68 jdolecek 2068 1.97 thorpej if_statinc(ifp, if_oerrors); 2069 1.68 jdolecek 2070 1.68 jdolecek /* XXX Resets both ports; we shouldn't do that. */ 2071 1.68 jdolecek mskc_reset(sc_if->sk_softc); 2072 1.68 jdolecek msk_reset(sc_if); 2073 1.68 jdolecek msk_init(ifp); 2074 1.1 riz } 2075 1.1 riz } 2076 1.1 riz 2077 1.20 joerg static bool 2078 1.33 dyoung mskc_suspend(device_t dv, const pmf_qual_t *qual) 2079 1.1 riz { 2080 1.20 joerg struct sk_softc *sc = device_private(dv); 2081 1.1 riz 2082 1.20 joerg DPRINTFN(2, ("mskc_suspend\n")); 2083 1.1 riz 2084 1.1 riz /* Turn off the 'driver is loaded' LED. */ 2085 1.1 riz CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_OFF); 2086 1.1 riz 2087 1.20 joerg return true; 2088 1.20 joerg } 2089 1.20 joerg 2090 1.20 joerg static bool 2091 1.33 dyoung mskc_resume(device_t dv, const pmf_qual_t *qual) 2092 1.20 joerg { 2093 1.20 joerg struct sk_softc *sc = device_private(dv); 2094 1.20 joerg 2095 1.20 joerg DPRINTFN(2, ("mskc_resume\n")); 2096 1.20 joerg 2097 1.63 jdolecek mskc_reset(sc); 2098 1.20 joerg CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_ON); 2099 1.20 joerg 2100 1.20 joerg return true; 2101 1.1 riz } 2102 1.1 riz 2103 1.38 plunky static __inline int 2104 1.83 msaitoh msk_rxvalid(struct sk_softc *sc, uint32_t stat, uint32_t len) 2105 1.1 riz { 2106 1.1 riz if ((stat & (YU_RXSTAT_CRCERR | YU_RXSTAT_LONGERR | 2107 1.1 riz YU_RXSTAT_MIIERR | YU_RXSTAT_BADFC | YU_RXSTAT_GOODFC | 2108 1.1 riz YU_RXSTAT_JABBER)) != 0 || 2109 1.1 riz (stat & YU_RXSTAT_RXOK) != YU_RXSTAT_RXOK || 2110 1.1 riz YU_RXSTAT_BYTES(stat) != len) 2111 1.88 msaitoh return 0; 2112 1.1 riz 2113 1.88 msaitoh return 1; 2114 1.1 riz } 2115 1.1 riz 2116 1.95 maxv static void 2117 1.83 msaitoh msk_rxeof(struct sk_if_softc *sc_if, uint16_t len, uint32_t rxstat) 2118 1.1 riz { 2119 1.1 riz struct sk_softc *sc = sc_if->sk_softc; 2120 1.1 riz struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; 2121 1.1 riz struct mbuf *m; 2122 1.78 jakllsch unsigned cur, prod, tail, total_len = len; 2123 1.1 riz bus_dmamap_t dmamap; 2124 1.1 riz 2125 1.1 riz cur = sc_if->sk_cdata.sk_rx_cons; 2126 1.78 jakllsch prod = sc_if->sk_cdata.sk_rx_prod; 2127 1.1 riz 2128 1.83 msaitoh DPRINTFN(2, ("msk_rxeof: cur %u prod %u rx_cnt %u\n", cur, prod, 2129 1.83 msaitoh sc_if->sk_cdata.sk_rx_cnt)); 2130 1.78 jakllsch 2131 1.78 jakllsch while (prod != cur) { 2132 1.106 jakllsch MSK_CDRXSYNC(sc_if, cur, 2133 1.106 jakllsch BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2134 1.106 jakllsch 2135 1.78 jakllsch tail = cur; 2136 1.78 jakllsch SK_INC(cur, MSK_RX_RING_CNT); 2137 1.78 jakllsch 2138 1.78 jakllsch sc_if->sk_cdata.sk_rx_cnt--; 2139 1.78 jakllsch m = sc_if->sk_cdata.sk_rx_chain[tail].sk_mbuf; 2140 1.78 jakllsch sc_if->sk_cdata.sk_rx_chain[tail].sk_mbuf = NULL; 2141 1.78 jakllsch if (m != NULL) 2142 1.78 jakllsch break; /* found it */ 2143 1.78 jakllsch } 2144 1.78 jakllsch sc_if->sk_cdata.sk_rx_cons = cur; 2145 1.83 msaitoh DPRINTFN(2, ("msk_rxeof: cur %u rx_cnt %u m %p\n", cur, 2146 1.83 msaitoh sc_if->sk_cdata.sk_rx_cnt, m)); 2147 1.78 jakllsch 2148 1.78 jakllsch if (m == NULL) 2149 1.42 riastrad return; 2150 1.42 riastrad 2151 1.106 jakllsch dmamap = sc_if->sk_cdata.sk_rx_chain[tail].sk_dmamap; 2152 1.68 jdolecek 2153 1.1 riz bus_dmamap_sync(sc_if->sk_softc->sc_dmatag, dmamap, 0, 2154 1.106 jakllsch uimin(dmamap->dm_mapsize, total_len), BUS_DMASYNC_POSTREAD); 2155 1.106 jakllsch bus_dmamap_unload(sc->sc_dmatag, dmamap); 2156 1.1 riz 2157 1.1 riz if (total_len < SK_MIN_FRAMELEN || 2158 1.19 dyoung total_len > ETHER_MAX_LEN_JUMBO || 2159 1.1 riz msk_rxvalid(sc, rxstat, total_len) == 0) { 2160 1.97 thorpej if_statinc(ifp, if_ierrors); 2161 1.72 jdolecek m_freem(m); 2162 1.1 riz return; 2163 1.1 riz } 2164 1.1 riz 2165 1.72 jdolecek m_set_rcvif(m, ifp); 2166 1.72 jdolecek m->m_pkthdr.len = m->m_len = total_len; 2167 1.1 riz 2168 1.1 riz /* pass it on. */ 2169 1.49 ozaki if_percpuq_enqueue(ifp->if_percpuq, m); 2170 1.1 riz } 2171 1.1 riz 2172 1.95 maxv static void 2173 1.68 jdolecek msk_txeof(struct sk_if_softc *sc_if) 2174 1.1 riz { 2175 1.1 riz struct sk_softc *sc = sc_if->sk_softc; 2176 1.1 riz struct msk_tx_desc *cur_tx; 2177 1.1 riz struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; 2178 1.83 msaitoh uint32_t idx, reg, sk_ctl; 2179 1.105 jakllsch bus_dmamap_t dmamap; 2180 1.1 riz 2181 1.1 riz DPRINTFN(2, ("msk_txeof\n")); 2182 1.1 riz 2183 1.68 jdolecek if (sc_if->sk_port == SK_PORT_A) 2184 1.68 jdolecek reg = SK_STAT_BMU_TXA1_RIDX; 2185 1.68 jdolecek else 2186 1.68 jdolecek reg = SK_STAT_BMU_TXA2_RIDX; 2187 1.68 jdolecek 2188 1.1 riz /* 2189 1.1 riz * Go through our tx ring and free mbufs for those 2190 1.1 riz * frames that have been sent. 2191 1.1 riz */ 2192 1.68 jdolecek idx = sc_if->sk_cdata.sk_tx_cons; 2193 1.68 jdolecek while (idx != sk_win_read_2(sc, reg)) { 2194 1.68 jdolecek MSK_CDTXSYNC(sc_if, idx, 1, 2195 1.88 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2196 1.17 kiyohara 2197 1.68 jdolecek cur_tx = &sc_if->sk_rdata->sk_tx_ring[idx]; 2198 1.5 msaitoh sk_ctl = cur_tx->sk_ctl; 2199 1.1 riz #ifdef MSK_DEBUG 2200 1.1 riz if (mskdebug >= 2) 2201 1.68 jdolecek msk_dump_txdesc(cur_tx, idx); 2202 1.1 riz #endif 2203 1.5 msaitoh if (sk_ctl & SK_Y2_TXCTL_LASTFRAG) 2204 1.97 thorpej if_statinc(ifp, if_opackets); 2205 1.68 jdolecek if (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf != NULL) { 2206 1.105 jakllsch dmamap = sc_if->sk_cdata.sk_tx_chain[idx].sk_dmamap; 2207 1.68 jdolecek 2208 1.105 jakllsch bus_dmamap_sync(sc->sc_dmatag, dmamap, 0, 2209 1.105 jakllsch dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); 2210 1.1 riz 2211 1.105 jakllsch bus_dmamap_unload(sc->sc_dmatag, dmamap); 2212 1.92 msaitoh m_freem(sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf); 2213 1.92 msaitoh sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf = NULL; 2214 1.1 riz } 2215 1.1 riz sc_if->sk_cdata.sk_tx_cnt--; 2216 1.68 jdolecek SK_INC(idx, MSK_TX_RING_CNT); 2217 1.1 riz } 2218 1.78 jakllsch if (idx == sc_if->sk_cdata.sk_tx_cons) 2219 1.78 jakllsch return; 2220 1.78 jakllsch 2221 1.1 riz ifp->if_timer = sc_if->sk_cdata.sk_tx_cnt > 0 ? 5 : 0; 2222 1.1 riz 2223 1.1 riz if (sc_if->sk_cdata.sk_tx_cnt < MSK_TX_RING_CNT - 2) 2224 1.1 riz ifp->if_flags &= ~IFF_OACTIVE; 2225 1.1 riz 2226 1.68 jdolecek sc_if->sk_cdata.sk_tx_cons = idx; 2227 1.68 jdolecek } 2228 1.68 jdolecek 2229 1.95 maxv static void 2230 1.68 jdolecek msk_fill_rx_ring(struct sk_if_softc *sc_if) 2231 1.68 jdolecek { 2232 1.68 jdolecek /* Make sure to not completely wrap around */ 2233 1.68 jdolecek while (sc_if->sk_cdata.sk_rx_cnt < (MSK_RX_RING_CNT - 1)) { 2234 1.106 jakllsch if (msk_newbuf(sc_if) == ENOBUFS) { 2235 1.72 jdolecek goto schedretry; 2236 1.68 jdolecek } 2237 1.68 jdolecek } 2238 1.72 jdolecek 2239 1.72 jdolecek return; 2240 1.72 jdolecek 2241 1.72 jdolecek schedretry: 2242 1.72 jdolecek /* Try later */ 2243 1.72 jdolecek callout_schedule(&sc_if->sk_tick_rx, hz/2); 2244 1.72 jdolecek } 2245 1.72 jdolecek 2246 1.72 jdolecek static void 2247 1.72 jdolecek msk_fill_rx_tick(void *xsc_if) 2248 1.72 jdolecek { 2249 1.72 jdolecek struct sk_if_softc *sc_if = xsc_if; 2250 1.72 jdolecek int s, rx_prod; 2251 1.72 jdolecek 2252 1.89 msaitoh KASSERT(KERNEL_LOCKED_P()); /* XXXSMP */ 2253 1.72 jdolecek 2254 1.72 jdolecek s = splnet(); 2255 1.72 jdolecek rx_prod = sc_if->sk_cdata.sk_rx_prod; 2256 1.72 jdolecek msk_fill_rx_ring(sc_if); 2257 1.72 jdolecek if (rx_prod != sc_if->sk_cdata.sk_rx_prod) { 2258 1.72 jdolecek SK_IF_WRITE_2(sc_if, 0, SK_RXQ1_Y2_PREF_PUTIDX, 2259 1.72 jdolecek sc_if->sk_cdata.sk_rx_prod); 2260 1.72 jdolecek } 2261 1.72 jdolecek splx(s); 2262 1.1 riz } 2263 1.1 riz 2264 1.95 maxv static void 2265 1.5 msaitoh msk_tick(void *xsc_if) 2266 1.1 riz { 2267 1.59 jdolecek struct sk_if_softc *sc_if = xsc_if; 2268 1.1 riz struct mii_data *mii = &sc_if->sk_mii; 2269 1.22 chris int s; 2270 1.1 riz 2271 1.22 chris s = splnet(); 2272 1.62 jdolecek mii_tick(mii); 2273 1.22 chris splx(s); 2274 1.22 chris 2275 1.1 riz callout_schedule(&sc_if->sk_tick_ch, hz); 2276 1.1 riz } 2277 1.1 riz 2278 1.95 maxv static void 2279 1.1 riz msk_intr_yukon(struct sk_if_softc *sc_if) 2280 1.1 riz { 2281 1.83 msaitoh uint8_t status; 2282 1.1 riz 2283 1.1 riz status = SK_IF_READ_1(sc_if, 0, SK_GMAC_ISR); 2284 1.1 riz /* RX overrun */ 2285 1.1 riz if ((status & SK_GMAC_INT_RX_OVER) != 0) { 2286 1.1 riz SK_IF_WRITE_1(sc_if, 0, SK_RXMF1_CTRL_TEST, 2287 1.1 riz SK_RFCTL_RX_FIFO_OVER); 2288 1.1 riz } 2289 1.1 riz /* TX underrun */ 2290 1.1 riz if ((status & SK_GMAC_INT_TX_UNDER) != 0) { 2291 1.6 msaitoh SK_IF_WRITE_1(sc_if, 0, SK_TXMF1_CTRL_TEST, 2292 1.1 riz SK_TFCTL_TX_FIFO_UNDER); 2293 1.1 riz } 2294 1.1 riz 2295 1.1 riz DPRINTFN(2, ("msk_intr_yukon status=%#x\n", status)); 2296 1.1 riz } 2297 1.1 riz 2298 1.95 maxv static int 2299 1.1 riz msk_intr(void *xsc) 2300 1.1 riz { 2301 1.1 riz struct sk_softc *sc = xsc; 2302 1.68 jdolecek struct sk_if_softc *sc_if; 2303 1.1 riz struct sk_if_softc *sc_if0 = sc->sk_if[SK_PORT_A]; 2304 1.1 riz struct sk_if_softc *sc_if1 = sc->sk_if[SK_PORT_B]; 2305 1.1 riz struct ifnet *ifp0 = NULL, *ifp1 = NULL; 2306 1.83 msaitoh uint32_t status; 2307 1.1 riz struct msk_status_desc *cur_st; 2308 1.113 jakllsch bool retried = false; 2309 1.1 riz 2310 1.1 riz status = CSR_READ_4(sc, SK_Y2_ISSR2); 2311 1.68 jdolecek if (status == 0xffffffff) 2312 1.88 msaitoh return 0; 2313 1.1 riz if (status == 0) { 2314 1.1 riz CSR_WRITE_4(sc, SK_Y2_ICR, 2); 2315 1.88 msaitoh return 0; 2316 1.1 riz } 2317 1.1 riz 2318 1.1 riz status = CSR_READ_4(sc, SK_ISR); 2319 1.1 riz 2320 1.1 riz if (sc_if0 != NULL) 2321 1.1 riz ifp0 = &sc_if0->sk_ethercom.ec_if; 2322 1.1 riz if (sc_if1 != NULL) 2323 1.1 riz ifp1 = &sc_if1->sk_ethercom.ec_if; 2324 1.1 riz 2325 1.1 riz if (sc_if0 && (status & SK_Y2_IMR_MAC1) && 2326 1.1 riz (ifp0->if_flags & IFF_RUNNING)) { 2327 1.1 riz msk_intr_yukon(sc_if0); 2328 1.1 riz } 2329 1.1 riz 2330 1.1 riz if (sc_if1 && (status & SK_Y2_IMR_MAC2) && 2331 1.1 riz (ifp1->if_flags & IFF_RUNNING)) { 2332 1.1 riz msk_intr_yukon(sc_if1); 2333 1.1 riz } 2334 1.1 riz 2335 1.113 jakllsch again: 2336 1.68 jdolecek MSK_CDSTSYNC(sc, sc->sk_status_idx, 2337 1.88 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2338 1.68 jdolecek cur_st = &sc->sk_status_ring[sc->sk_status_idx]; 2339 1.5 msaitoh 2340 1.68 jdolecek while (cur_st->sk_opcode & SK_Y2_STOPC_OWN) { 2341 1.68 jdolecek cur_st->sk_opcode &= ~SK_Y2_STOPC_OWN; 2342 1.68 jdolecek switch (cur_st->sk_opcode) { 2343 1.1 riz case SK_Y2_STOPC_RXSTAT: 2344 1.68 jdolecek sc_if = sc->sk_if[cur_st->sk_link & 0x01]; 2345 1.81 bouyer if (sc_if) { 2346 1.81 bouyer msk_rxeof(sc_if, letoh16(cur_st->sk_len), 2347 1.81 bouyer letoh32(cur_st->sk_status)); 2348 1.81 bouyer if (sc_if->sk_cdata.sk_rx_cnt < (MSK_RX_RING_CNT/3)) 2349 1.81 bouyer msk_fill_rx_tick(sc_if); 2350 1.81 bouyer } 2351 1.1 riz break; 2352 1.1 riz case SK_Y2_STOPC_TXSTAT: 2353 1.5 msaitoh if (sc_if0) 2354 1.68 jdolecek msk_txeof(sc_if0); 2355 1.5 msaitoh if (sc_if1) 2356 1.68 jdolecek msk_txeof(sc_if1); 2357 1.1 riz break; 2358 1.1 riz default: 2359 1.68 jdolecek aprint_error("opcode=0x%x\n", cur_st->sk_opcode); 2360 1.1 riz break; 2361 1.1 riz } 2362 1.1 riz SK_INC(sc->sk_status_idx, MSK_STATUS_RING_CNT); 2363 1.5 msaitoh 2364 1.68 jdolecek MSK_CDSTSYNC(sc, sc->sk_status_idx, 2365 1.88 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2366 1.68 jdolecek cur_st = &sc->sk_status_ring[sc->sk_status_idx]; 2367 1.1 riz } 2368 1.1 riz 2369 1.113 jakllsch if (CSR_READ_2(sc, SK_STAT_BMU_PUTIDX) == sc->sk_status_idx) { 2370 1.1 riz CSR_WRITE_4(sc, SK_STAT_BMU_CSR, SK_STAT_BMU_IRQ_CLEAR); 2371 1.113 jakllsch } else if (!retried) { 2372 1.113 jakllsch retried = true; 2373 1.113 jakllsch goto again; 2374 1.1 riz } 2375 1.1 riz 2376 1.1 riz CSR_WRITE_4(sc, SK_Y2_ICR, 2); 2377 1.1 riz 2378 1.68 jdolecek if (ifp0 != NULL && !IFQ_IS_EMPTY(&ifp0->if_snd)) 2379 1.53 ozaki if_schedule_deferred_start(ifp0); 2380 1.68 jdolecek if (ifp1 != NULL && !IFQ_IS_EMPTY(&ifp1->if_snd)) 2381 1.53 ozaki if_schedule_deferred_start(ifp1); 2382 1.1 riz 2383 1.69 jdolecek KASSERT(sc->rnd_attached > 0); 2384 1.39 tls rnd_add_uint32(&sc->rnd_source, status); 2385 1.1 riz 2386 1.1 riz if (sc->sk_int_mod_pending) 2387 1.30 christos msk_update_int_mod(sc, 1); 2388 1.1 riz 2389 1.112 jakllsch return (status & sc->sk_intrmask) != 0; 2390 1.1 riz } 2391 1.1 riz 2392 1.95 maxv static void 2393 1.1 riz msk_init_yukon(struct sk_if_softc *sc_if) 2394 1.1 riz { 2395 1.83 msaitoh uint32_t v; 2396 1.83 msaitoh uint16_t reg; 2397 1.1 riz struct sk_softc *sc; 2398 1.1 riz int i; 2399 1.1 riz 2400 1.1 riz sc = sc_if->sk_softc; 2401 1.1 riz 2402 1.1 riz DPRINTFN(2, ("msk_init_yukon: start: sk_csr=%#x\n", 2403 1.1 riz CSR_READ_4(sc_if->sk_softc, SK_CSR))); 2404 1.1 riz 2405 1.1 riz DPRINTFN(6, ("msk_init_yukon: 1\n")); 2406 1.1 riz 2407 1.1 riz DPRINTFN(3, ("msk_init_yukon: gmac_ctrl=%#x\n", 2408 1.1 riz SK_IF_READ_4(sc_if, 0, SK_GMAC_CTRL))); 2409 1.1 riz 2410 1.1 riz DPRINTFN(6, ("msk_init_yukon: 3\n")); 2411 1.1 riz 2412 1.1 riz /* unused read of the interrupt source register */ 2413 1.1 riz DPRINTFN(6, ("msk_init_yukon: 4\n")); 2414 1.1 riz SK_IF_READ_2(sc_if, 0, SK_GMAC_ISR); 2415 1.1 riz 2416 1.1 riz DPRINTFN(6, ("msk_init_yukon: 4a\n")); 2417 1.1 riz reg = SK_YU_READ_2(sc_if, YUKON_PAR); 2418 1.1 riz DPRINTFN(6, ("msk_init_yukon: YUKON_PAR=%#x\n", reg)); 2419 1.1 riz 2420 1.1 riz /* MIB Counter Clear Mode set */ 2421 1.59 jdolecek reg |= YU_PAR_MIB_CLR; 2422 1.1 riz DPRINTFN(6, ("msk_init_yukon: YUKON_PAR=%#x\n", reg)); 2423 1.1 riz DPRINTFN(6, ("msk_init_yukon: 4b\n")); 2424 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_PAR, reg); 2425 1.1 riz 2426 1.1 riz /* MIB Counter Clear Mode clear */ 2427 1.1 riz DPRINTFN(6, ("msk_init_yukon: 5\n")); 2428 1.59 jdolecek reg &= ~YU_PAR_MIB_CLR; 2429 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_PAR, reg); 2430 1.1 riz 2431 1.1 riz /* receive control reg */ 2432 1.1 riz DPRINTFN(6, ("msk_init_yukon: 7\n")); 2433 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_RCR, YU_RCR_CRCR); 2434 1.1 riz 2435 1.6 msaitoh /* transmit control register */ 2436 1.6 msaitoh SK_YU_WRITE_2(sc_if, YUKON_TCR, (0x04 << 10)); 2437 1.6 msaitoh 2438 1.6 msaitoh /* transmit flow control register */ 2439 1.6 msaitoh SK_YU_WRITE_2(sc_if, YUKON_TFCR, 0xffff); 2440 1.6 msaitoh 2441 1.1 riz /* transmit parameter register */ 2442 1.1 riz DPRINTFN(6, ("msk_init_yukon: 8\n")); 2443 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_TPR, YU_TPR_JAM_LEN(0x3) | 2444 1.6 msaitoh YU_TPR_JAM_IPG(0xb) | YU_TPR_JAM2DATA_IPG(0x1c) | 0x04); 2445 1.1 riz 2446 1.1 riz /* serial mode register */ 2447 1.1 riz DPRINTFN(6, ("msk_init_yukon: 9\n")); 2448 1.5 msaitoh reg = YU_SMR_DATA_BLIND(0x1c) | 2449 1.5 msaitoh YU_SMR_MFL_VLAN | 2450 1.5 msaitoh YU_SMR_IPG_DATA(0x1e); 2451 1.5 msaitoh 2452 1.56 jdolecek if (sc->sk_type != SK_YUKON_FE && 2453 1.60 jdolecek sc->sk_type != SK_YUKON_FE_P) 2454 1.5 msaitoh reg |= YU_SMR_MFL_JUMBO; 2455 1.5 msaitoh 2456 1.5 msaitoh SK_YU_WRITE_2(sc_if, YUKON_SMR, reg); 2457 1.1 riz 2458 1.1 riz DPRINTFN(6, ("msk_init_yukon: 10\n")); 2459 1.50 pgoyette struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; 2460 1.50 pgoyette /* msk_attach calls me before ether_ifattach so check null */ 2461 1.50 pgoyette if (ifp != NULL && ifp->if_sadl != NULL) 2462 1.50 pgoyette memcpy(sc_if->sk_enaddr, CLLADDR(ifp->if_sadl), 2463 1.50 pgoyette sizeof(sc_if->sk_enaddr)); 2464 1.1 riz /* Setup Yukon's address */ 2465 1.1 riz for (i = 0; i < 3; i++) { 2466 1.1 riz /* Write Source Address 1 (unicast filter) */ 2467 1.43 christos SK_YU_WRITE_2(sc_if, YUKON_SAL1 + i * 4, 2468 1.1 riz sc_if->sk_enaddr[i * 2] | 2469 1.1 riz sc_if->sk_enaddr[i * 2 + 1] << 8); 2470 1.1 riz } 2471 1.1 riz 2472 1.1 riz for (i = 0; i < 3; i++) { 2473 1.1 riz reg = sk_win_read_2(sc_if->sk_softc, 2474 1.1 riz SK_MAC1_0 + i * 2 + sc_if->sk_port * 8); 2475 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_SAL2 + i * 4, reg); 2476 1.1 riz } 2477 1.1 riz 2478 1.1 riz /* Set promiscuous mode */ 2479 1.1 riz msk_setpromisc(sc_if); 2480 1.1 riz 2481 1.1 riz /* Set multicast filter */ 2482 1.1 riz DPRINTFN(6, ("msk_init_yukon: 11\n")); 2483 1.1 riz msk_setmulti(sc_if); 2484 1.1 riz 2485 1.1 riz /* enable interrupt mask for counter overflows */ 2486 1.1 riz DPRINTFN(6, ("msk_init_yukon: 12\n")); 2487 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_TIMR, 0); 2488 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_RIMR, 0); 2489 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_TRIMR, 0); 2490 1.1 riz 2491 1.1 riz /* Configure RX MAC FIFO Flush Mask */ 2492 1.1 riz v = YU_RXSTAT_FOFL | YU_RXSTAT_CRCERR | YU_RXSTAT_MIIERR | 2493 1.1 riz YU_RXSTAT_BADFC | YU_RXSTAT_GOODFC | YU_RXSTAT_RUNT | 2494 1.1 riz YU_RXSTAT_JABBER; 2495 1.1 riz SK_IF_WRITE_2(sc_if, 0, SK_RXMF1_FLUSH_MASK, v); 2496 1.1 riz 2497 1.1 riz /* Configure RX MAC FIFO */ 2498 1.1 riz SK_IF_WRITE_1(sc_if, 0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_CLEAR); 2499 1.94 msaitoh v = SK_RFCTL_OPERATION_ON | SK_RFCTL_FIFO_FLUSH_ON; 2500 1.94 msaitoh if ((sc->sk_type == SK_YUKON_EX) || (sc->sk_type == SK_YUKON_FE_P)) 2501 1.94 msaitoh v |= SK_RFCTL_RX_OVER_ON; 2502 1.94 msaitoh SK_IF_WRITE_2(sc_if, 0, SK_RXMF1_CTRL_TEST, v); 2503 1.94 msaitoh 2504 1.94 msaitoh if ((sc->sk_type == SK_YUKON_FE_P) && 2505 1.94 msaitoh (sc->sk_rev == SK_YUKON_FE_P_REV_A0)) 2506 1.94 msaitoh v = 0x178; /* Magic value */ 2507 1.94 msaitoh else { 2508 1.94 msaitoh /* Increase flush threshold to 64 bytes */ 2509 1.94 msaitoh v = SK_RFCTL_FIFO_THRESHOLD + 1; 2510 1.94 msaitoh } 2511 1.94 msaitoh SK_IF_WRITE_2(sc_if, 0, SK_RXMF1_FLUSH_THRESHOLD, v); 2512 1.1 riz 2513 1.1 riz /* Configure TX MAC FIFO */ 2514 1.1 riz SK_IF_WRITE_1(sc_if, 0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_CLEAR); 2515 1.1 riz SK_IF_WRITE_2(sc_if, 0, SK_TXMF1_CTRL_TEST, SK_TFCTL_OPERATION_ON); 2516 1.1 riz 2517 1.94 msaitoh if ((sc->sk_type == SK_YUKON_FE_P) && 2518 1.94 msaitoh (sc->sk_rev == SK_YUKON_FE_P_REV_A0)) { 2519 1.94 msaitoh v = SK_IF_READ_2(sc_if, 0, SK_TXMF1_END); 2520 1.94 msaitoh v &= ~SK_TXEND_WM_ON; 2521 1.94 msaitoh SK_IF_WRITE_2(sc_if, 0, SK_TXMF1_END, v); 2522 1.94 msaitoh } 2523 1.94 msaitoh 2524 1.1 riz #if 1 2525 1.1 riz SK_YU_WRITE_2(sc_if, YUKON_GPCR, YU_GPCR_TXEN | YU_GPCR_RXEN); 2526 1.1 riz #endif 2527 1.1 riz DPRINTFN(6, ("msk_init_yukon: end\n")); 2528 1.1 riz } 2529 1.1 riz 2530 1.1 riz /* 2531 1.1 riz * Note that to properly initialize any part of the GEnesis chip, 2532 1.1 riz * you first have to take it out of reset mode. 2533 1.1 riz */ 2534 1.95 maxv static int 2535 1.1 riz msk_init(struct ifnet *ifp) 2536 1.1 riz { 2537 1.1 riz struct sk_if_softc *sc_if = ifp->if_softc; 2538 1.1 riz struct sk_softc *sc = sc_if->sk_softc; 2539 1.15 dyoung int rc = 0, s; 2540 1.5 msaitoh uint32_t imr, imtimer_ticks; 2541 1.1 riz 2542 1.1 riz 2543 1.1 riz DPRINTFN(2, ("msk_init\n")); 2544 1.1 riz 2545 1.1 riz s = splnet(); 2546 1.1 riz 2547 1.1 riz /* Cancel pending I/O and free all RX/TX buffers. */ 2548 1.68 jdolecek msk_stop(ifp, 1); 2549 1.1 riz 2550 1.1 riz /* Configure I2C registers */ 2551 1.1 riz 2552 1.1 riz /* Configure XMAC(s) */ 2553 1.1 riz msk_init_yukon(sc_if); 2554 1.15 dyoung if ((rc = ether_mediachange(ifp)) != 0) 2555 1.15 dyoung goto out; 2556 1.1 riz 2557 1.1 riz /* Configure transmit arbiter(s) */ 2558 1.1 riz SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL, SK_TXARCTL_ON); 2559 1.1 riz #if 0 2560 1.94 msaitoh /* SK_TXARCTL_ON | SK_TXARCTL_FSYNC_ON); */ 2561 1.1 riz #endif 2562 1.1 riz 2563 1.78 jakllsch if (sc->sk_ramsize) { 2564 1.78 jakllsch /* Configure RAMbuffers */ 2565 1.78 jakllsch SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_UNRESET); 2566 1.78 jakllsch SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_START, sc_if->sk_rx_ramstart); 2567 1.78 jakllsch SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_WR_PTR, sc_if->sk_rx_ramstart); 2568 1.78 jakllsch SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_RD_PTR, sc_if->sk_rx_ramstart); 2569 1.78 jakllsch SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_END, sc_if->sk_rx_ramend); 2570 1.78 jakllsch SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_ON); 2571 1.78 jakllsch 2572 1.78 jakllsch SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_CTLTST, SK_RBCTL_UNRESET); 2573 1.78 jakllsch SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_CTLTST, SK_RBCTL_STORENFWD_ON); 2574 1.78 jakllsch SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_START, sc_if->sk_tx_ramstart); 2575 1.78 jakllsch SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_WR_PTR, sc_if->sk_tx_ramstart); 2576 1.78 jakllsch SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_RD_PTR, sc_if->sk_tx_ramstart); 2577 1.78 jakllsch SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_END, sc_if->sk_tx_ramend); 2578 1.78 jakllsch SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_CTLTST, SK_RBCTL_ON); 2579 1.78 jakllsch } 2580 1.1 riz 2581 1.1 riz /* Configure BMUs */ 2582 1.1 riz SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, 0x00000016); 2583 1.1 riz SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, 0x00000d28); 2584 1.1 riz SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, 0x00000080); 2585 1.6 msaitoh SK_IF_WRITE_2(sc_if, 0, SK_RXQ1_Y2_WM, 0x0600); /* XXX ??? */ 2586 1.1 riz 2587 1.1 riz SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_BMU_CSR, 0x00000016); 2588 1.1 riz SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_BMU_CSR, 0x00000d28); 2589 1.1 riz SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_BMU_CSR, 0x00000080); 2590 1.6 msaitoh SK_IF_WRITE_2(sc_if, 1, SK_TXQA1_Y2_WM, 0x0600); /* XXX ??? */ 2591 1.1 riz 2592 1.1 riz /* Make sure the sync transmit queue is disabled. */ 2593 1.1 riz SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_RESET); 2594 1.1 riz 2595 1.1 riz /* Init descriptors */ 2596 1.1 riz if (msk_init_rx_ring(sc_if) == ENOBUFS) { 2597 1.30 christos aprint_error_dev(sc_if->sk_dev, "initialization failed: no " 2598 1.18 cegger "memory for rx buffers\n"); 2599 1.68 jdolecek msk_stop(ifp, 1); 2600 1.1 riz splx(s); 2601 1.1 riz return ENOBUFS; 2602 1.1 riz } 2603 1.1 riz 2604 1.1 riz if (msk_init_tx_ring(sc_if) == ENOBUFS) { 2605 1.30 christos aprint_error_dev(sc_if->sk_dev, "initialization failed: no " 2606 1.18 cegger "memory for tx buffers\n"); 2607 1.68 jdolecek msk_stop(ifp, 1); 2608 1.1 riz splx(s); 2609 1.1 riz return ENOBUFS; 2610 1.1 riz } 2611 1.1 riz 2612 1.1 riz /* Set interrupt moderation if changed via sysctl. */ 2613 1.1 riz switch (sc->sk_type) { 2614 1.1 riz case SK_YUKON_EC: 2615 1.6 msaitoh case SK_YUKON_EC_U: 2616 1.56 jdolecek case SK_YUKON_EX: 2617 1.56 jdolecek case SK_YUKON_SUPR: 2618 1.56 jdolecek case SK_YUKON_ULTRA2: 2619 1.56 jdolecek case SK_YUKON_OPTIMA: 2620 1.56 jdolecek case SK_YUKON_PRM: 2621 1.56 jdolecek case SK_YUKON_OPTIMA2: 2622 1.5 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON_EC; 2623 1.1 riz break; 2624 1.6 msaitoh case SK_YUKON_FE: 2625 1.6 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON_FE; 2626 1.6 msaitoh break; 2627 1.60 jdolecek case SK_YUKON_FE_P: 2628 1.60 jdolecek imtimer_ticks = SK_IMTIMER_TICKS_YUKON_FE_P; 2629 1.60 jdolecek break; 2630 1.6 msaitoh case SK_YUKON_XL: 2631 1.6 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON_XL; 2632 1.6 msaitoh break; 2633 1.1 riz default: 2634 1.5 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON; 2635 1.1 riz } 2636 1.1 riz imr = sk_win_read_4(sc, SK_IMTIMERINIT); 2637 1.1 riz if (imr != SK_IM_USECS(sc->sk_int_mod)) { 2638 1.1 riz sk_win_write_4(sc, SK_IMTIMERINIT, 2639 1.1 riz SK_IM_USECS(sc->sk_int_mod)); 2640 1.30 christos aprint_verbose_dev(sc->sk_dev, 2641 1.34 tnn "interrupt moderation is %d us\n", sc->sk_int_mod); 2642 1.1 riz } 2643 1.1 riz 2644 1.1 riz /* Initialize prefetch engine. */ 2645 1.1 riz SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_CSR, 0x00000001); 2646 1.1 riz SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_CSR, 0x00000002); 2647 1.1 riz SK_IF_WRITE_2(sc_if, 0, SK_RXQ1_Y2_PREF_LIDX, MSK_RX_RING_CNT - 1); 2648 1.1 riz SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_ADDRLO, 2649 1.1 riz MSK_RX_RING_ADDR(sc_if, 0)); 2650 1.1 riz SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_ADDRHI, 2651 1.83 msaitoh (uint64_t)MSK_RX_RING_ADDR(sc_if, 0) >> 32); 2652 1.1 riz SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_CSR, 0x00000008); 2653 1.1 riz SK_IF_READ_4(sc_if, 0, SK_RXQ1_Y2_PREF_CSR); 2654 1.1 riz 2655 1.1 riz SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_CSR, 0x00000001); 2656 1.1 riz SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_CSR, 0x00000002); 2657 1.1 riz SK_IF_WRITE_2(sc_if, 1, SK_TXQA1_Y2_PREF_LIDX, MSK_TX_RING_CNT - 1); 2658 1.1 riz SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_ADDRLO, 2659 1.1 riz MSK_TX_RING_ADDR(sc_if, 0)); 2660 1.1 riz SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_ADDRHI, 2661 1.83 msaitoh (uint64_t)MSK_TX_RING_ADDR(sc_if, 0) >> 32); 2662 1.1 riz SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_CSR, 0x00000008); 2663 1.1 riz SK_IF_READ_4(sc_if, 1, SK_TXQA1_Y2_PREF_CSR); 2664 1.1 riz 2665 1.1 riz SK_IF_WRITE_2(sc_if, 0, SK_RXQ1_Y2_PREF_PUTIDX, 2666 1.1 riz sc_if->sk_cdata.sk_rx_prod); 2667 1.1 riz 2668 1.94 msaitoh 2669 1.94 msaitoh if ((sc->sk_type == SK_YUKON_EX) || (sc->sk_type == SK_YUKON_SUPR)) { 2670 1.94 msaitoh /* Disable flushing of non-ASF packets. */ 2671 1.94 msaitoh SK_IF_WRITE_4(sc_if, 0, SK_RXMF1_CTRL_TEST, 2672 1.94 msaitoh SK_RFCTL_RX_MACSEC_FLUSH_OFF); 2673 1.94 msaitoh } 2674 1.94 msaitoh 2675 1.1 riz /* Configure interrupt handling */ 2676 1.1 riz if (sc_if->sk_port == SK_PORT_A) 2677 1.1 riz sc->sk_intrmask |= SK_Y2_INTRS1; 2678 1.1 riz else 2679 1.1 riz sc->sk_intrmask |= SK_Y2_INTRS2; 2680 1.1 riz sc->sk_intrmask |= SK_Y2_IMR_BMU; 2681 1.1 riz CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask); 2682 1.1 riz 2683 1.1 riz ifp->if_flags |= IFF_RUNNING; 2684 1.1 riz ifp->if_flags &= ~IFF_OACTIVE; 2685 1.1 riz 2686 1.1 riz callout_schedule(&sc_if->sk_tick_ch, hz); 2687 1.1 riz 2688 1.15 dyoung out: 2689 1.1 riz splx(s); 2690 1.15 dyoung return rc; 2691 1.1 riz } 2692 1.1 riz 2693 1.68 jdolecek /* 2694 1.68 jdolecek * Note: the logic of second parameter is inverted compared to OpenBSD 2695 1.68 jdolecek * code, since this code uses the function as if_stop hook too. 2696 1.68 jdolecek */ 2697 1.95 maxv static void 2698 1.3 christos msk_stop(struct ifnet *ifp, int disable) 2699 1.1 riz { 2700 1.1 riz struct sk_if_softc *sc_if = ifp->if_softc; 2701 1.1 riz struct sk_softc *sc = sc_if->sk_softc; 2702 1.105 jakllsch bus_dmamap_t dmamap; 2703 1.1 riz int i; 2704 1.1 riz 2705 1.1 riz DPRINTFN(2, ("msk_stop\n")); 2706 1.1 riz 2707 1.1 riz callout_stop(&sc_if->sk_tick_ch); 2708 1.72 jdolecek callout_stop(&sc_if->sk_tick_rx); 2709 1.1 riz 2710 1.88 msaitoh ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 2711 1.1 riz 2712 1.1 riz /* Stop transfer of Tx descriptors */ 2713 1.1 riz 2714 1.1 riz /* Stop transfer of Rx descriptors */ 2715 1.1 riz 2716 1.68 jdolecek if (disable) { 2717 1.68 jdolecek /* Turn off various components of this interface. */ 2718 1.68 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_SET); 2719 1.68 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_SET); 2720 1.68 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_OFFLINE); 2721 1.88 msaitoh SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_RESET | SK_RBCTL_OFF); 2722 1.68 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_BMU_CSR, SK_TXBMU_OFFLINE); 2723 1.88 msaitoh SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_CTLTST, SK_RBCTL_RESET | SK_RBCTL_OFF); 2724 1.68 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL, SK_TXARCTL_OFF); 2725 1.68 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL, SK_RXLEDCTL_COUNTER_STOP); 2726 1.68 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL, SK_TXLEDCTL_COUNTER_STOP); 2727 1.68 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_OFF); 2728 1.68 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_LINKSYNC_OFF); 2729 1.68 jdolecek 2730 1.68 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_CSR, 0x00000001); 2731 1.68 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_CSR, 0x00000001); 2732 1.68 jdolecek 2733 1.68 jdolecek /* Disable interrupts */ 2734 1.68 jdolecek if (sc_if->sk_port == SK_PORT_A) 2735 1.68 jdolecek sc->sk_intrmask &= ~SK_Y2_INTRS1; 2736 1.68 jdolecek else 2737 1.68 jdolecek sc->sk_intrmask &= ~SK_Y2_INTRS2; 2738 1.68 jdolecek CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask); 2739 1.68 jdolecek } 2740 1.1 riz 2741 1.1 riz /* Free RX and TX mbufs still in the queues. */ 2742 1.1 riz for (i = 0; i < MSK_RX_RING_CNT; i++) { 2743 1.1 riz if (sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf != NULL) { 2744 1.106 jakllsch dmamap = sc_if->sk_cdata.sk_rx_chain[i].sk_dmamap; 2745 1.106 jakllsch 2746 1.106 jakllsch bus_dmamap_sync(sc->sc_dmatag, dmamap, 0, 2747 1.106 jakllsch dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); 2748 1.106 jakllsch 2749 1.106 jakllsch bus_dmamap_unload(sc->sc_dmatag, dmamap); 2750 1.106 jakllsch 2751 1.1 riz m_freem(sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf); 2752 1.1 riz sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf = NULL; 2753 1.1 riz } 2754 1.1 riz } 2755 1.1 riz 2756 1.68 jdolecek sc_if->sk_cdata.sk_rx_prod = 0; 2757 1.68 jdolecek sc_if->sk_cdata.sk_rx_cons = 0; 2758 1.68 jdolecek sc_if->sk_cdata.sk_rx_cnt = 0; 2759 1.68 jdolecek 2760 1.1 riz for (i = 0; i < MSK_TX_RING_CNT; i++) { 2761 1.1 riz if (sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf != NULL) { 2762 1.105 jakllsch dmamap = sc_if->sk_cdata.sk_tx_chain[i].sk_dmamap; 2763 1.92 msaitoh 2764 1.105 jakllsch bus_dmamap_sync(sc->sc_dmatag, dmamap, 0, 2765 1.105 jakllsch dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); 2766 1.99 jakllsch 2767 1.105 jakllsch bus_dmamap_unload(sc->sc_dmatag, dmamap); 2768 1.99 jakllsch 2769 1.92 msaitoh m_freem(sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf); 2770 1.92 msaitoh sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf = NULL; 2771 1.1 riz } 2772 1.1 riz } 2773 1.1 riz } 2774 1.1 riz 2775 1.70 jdolecek CFATTACH_DECL3_NEW(mskc, sizeof(struct sk_softc), mskc_probe, mskc_attach, 2776 1.70 jdolecek mskc_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); 2777 1.1 riz 2778 1.70 jdolecek CFATTACH_DECL3_NEW(msk, sizeof(struct sk_if_softc), msk_probe, msk_attach, 2779 1.70 jdolecek msk_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN); 2780 1.1 riz 2781 1.1 riz #ifdef MSK_DEBUG 2782 1.95 maxv static void 2783 1.1 riz msk_dump_txdesc(struct msk_tx_desc *le, int idx) 2784 1.1 riz { 2785 1.1 riz #define DESC_PRINT(X) \ 2786 1.83 msaitoh if (X) \ 2787 1.1 riz printf("txdesc[%d]." #X "=%#x\n", \ 2788 1.1 riz idx, X); 2789 1.1 riz 2790 1.1 riz DESC_PRINT(letoh32(le->sk_addr)); 2791 1.1 riz DESC_PRINT(letoh16(le->sk_len)); 2792 1.1 riz DESC_PRINT(le->sk_ctl); 2793 1.1 riz DESC_PRINT(le->sk_opcode); 2794 1.1 riz #undef DESC_PRINT 2795 1.1 riz } 2796 1.1 riz 2797 1.95 maxv static void 2798 1.1 riz msk_dump_bytes(const char *data, int len) 2799 1.1 riz { 2800 1.1 riz int c, i, j; 2801 1.1 riz 2802 1.1 riz for (i = 0; i < len; i += 16) { 2803 1.1 riz printf("%08x ", i); 2804 1.1 riz c = len - i; 2805 1.1 riz if (c > 16) c = 16; 2806 1.1 riz 2807 1.1 riz for (j = 0; j < c; j++) { 2808 1.1 riz printf("%02x ", data[i + j] & 0xff); 2809 1.1 riz if ((j & 0xf) == 7 && j > 0) 2810 1.1 riz printf(" "); 2811 1.1 riz } 2812 1.59 jdolecek 2813 1.1 riz for (; j < 16; j++) 2814 1.1 riz printf(" "); 2815 1.1 riz printf(" "); 2816 1.1 riz 2817 1.1 riz for (j = 0; j < c; j++) { 2818 1.1 riz int ch = data[i + j] & 0xff; 2819 1.1 riz printf("%c", ' ' <= ch && ch <= '~' ? ch : ' '); 2820 1.1 riz } 2821 1.59 jdolecek 2822 1.1 riz printf("\n"); 2823 1.59 jdolecek 2824 1.1 riz if (c < 16) 2825 1.1 riz break; 2826 1.1 riz } 2827 1.1 riz } 2828 1.1 riz 2829 1.95 maxv static void 2830 1.1 riz msk_dump_mbuf(struct mbuf *m) 2831 1.1 riz { 2832 1.1 riz int count = m->m_pkthdr.len; 2833 1.1 riz 2834 1.1 riz printf("m=%p, m->m_pkthdr.len=%d\n", m, m->m_pkthdr.len); 2835 1.1 riz 2836 1.1 riz while (count > 0 && m) { 2837 1.1 riz printf("m=%p, m->m_data=%p, m->m_len=%d\n", 2838 1.1 riz m, m->m_data, m->m_len); 2839 1.78 jakllsch if (mskdebug >= 4) 2840 1.78 jakllsch msk_dump_bytes(mtod(m, char *), m->m_len); 2841 1.1 riz 2842 1.1 riz count -= m->m_len; 2843 1.1 riz m = m->m_next; 2844 1.1 riz } 2845 1.1 riz } 2846 1.1 riz #endif 2847 1.1 riz 2848 1.1 riz static int 2849 1.1 riz msk_sysctl_handler(SYSCTLFN_ARGS) 2850 1.1 riz { 2851 1.1 riz int error, t; 2852 1.1 riz struct sysctlnode node; 2853 1.1 riz struct sk_softc *sc; 2854 1.1 riz 2855 1.1 riz node = *rnode; 2856 1.1 riz sc = node.sysctl_data; 2857 1.1 riz t = sc->sk_int_mod; 2858 1.1 riz node.sysctl_data = &t; 2859 1.1 riz error = sysctl_lookup(SYSCTLFN_CALL(&node)); 2860 1.1 riz if (error || newp == NULL) 2861 1.1 riz return error; 2862 1.1 riz 2863 1.1 riz if (t < SK_IM_MIN || t > SK_IM_MAX) 2864 1.1 riz return EINVAL; 2865 1.1 riz 2866 1.1 riz /* update the softc with sysctl-changed value, and mark 2867 1.1 riz for hardware update */ 2868 1.1 riz sc->sk_int_mod = t; 2869 1.1 riz sc->sk_int_mod_pending = 1; 2870 1.1 riz return 0; 2871 1.1 riz } 2872 1.1 riz 2873 1.1 riz /* 2874 1.68 jdolecek * Set up sysctl(3) MIB, hw.msk.* - Individual controllers will be 2875 1.68 jdolecek * set up in mskc_attach() 2876 1.1 riz */ 2877 1.1 riz SYSCTL_SETUP(sysctl_msk, "sysctl msk subtree setup") 2878 1.1 riz { 2879 1.1 riz int rc; 2880 1.1 riz const struct sysctlnode *node; 2881 1.1 riz 2882 1.1 riz if ((rc = sysctl_createv(clog, 0, NULL, &node, 2883 1.1 riz 0, CTLTYPE_NODE, "msk", 2884 1.1 riz SYSCTL_DESCR("msk interface controls"), 2885 1.1 riz NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) { 2886 1.1 riz goto err; 2887 1.1 riz } 2888 1.1 riz 2889 1.1 riz msk_root_num = node->sysctl_num; 2890 1.1 riz return; 2891 1.1 riz 2892 1.1 riz err: 2893 1.1 riz aprint_error("%s: syctl_createv failed (rc = %d)\n", __func__, rc); 2894 1.1 riz } 2895