1 1.113 rin /* $NetBSD: if_sk.c,v 1.113 2024/07/05 04:31:51 rin Exp $ */ 2 1.1 jdolecek 3 1.1 jdolecek /*- 4 1.1 jdolecek * Copyright (c) 2003 The NetBSD Foundation, Inc. 5 1.1 jdolecek * All rights reserved. 6 1.1 jdolecek * 7 1.1 jdolecek * Redistribution and use in source and binary forms, with or without 8 1.1 jdolecek * modification, are permitted provided that the following conditions 9 1.1 jdolecek * are met: 10 1.1 jdolecek * 1. Redistributions of source code must retain the above copyright 11 1.1 jdolecek * notice, this list of conditions and the following disclaimer. 12 1.1 jdolecek * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jdolecek * notice, this list of conditions and the following disclaimer in the 14 1.1 jdolecek * documentation and/or other materials provided with the distribution. 15 1.1 jdolecek * 16 1.1 jdolecek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.1 jdolecek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.1 jdolecek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 jdolecek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.1 jdolecek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.1 jdolecek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.1 jdolecek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 jdolecek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.1 jdolecek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.1 jdolecek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.1 jdolecek * POSSIBILITY OF SUCH DAMAGE. 27 1.1 jdolecek */ 28 1.1 jdolecek 29 1.29 riz /* $OpenBSD: if_sk.c,v 1.116 2006/06/22 23:06:03 brad Exp $ */ 30 1.1 jdolecek 31 1.1 jdolecek /* 32 1.1 jdolecek * Copyright (c) 1997, 1998, 1999, 2000 33 1.1 jdolecek * Bill Paul <wpaul (at) ctr.columbia.edu>. All rights reserved. 34 1.1 jdolecek * 35 1.1 jdolecek * Redistribution and use in source and binary forms, with or without 36 1.1 jdolecek * modification, are permitted provided that the following conditions 37 1.1 jdolecek * are met: 38 1.1 jdolecek * 1. Redistributions of source code must retain the above copyright 39 1.1 jdolecek * notice, this list of conditions and the following disclaimer. 40 1.1 jdolecek * 2. Redistributions in binary form must reproduce the above copyright 41 1.1 jdolecek * notice, this list of conditions and the following disclaimer in the 42 1.1 jdolecek * documentation and/or other materials provided with the distribution. 43 1.1 jdolecek * 3. All advertising materials mentioning features or use of this software 44 1.1 jdolecek * must display the following acknowledgement: 45 1.1 jdolecek * This product includes software developed by Bill Paul. 46 1.1 jdolecek * 4. Neither the name of the author nor the names of any co-contributors 47 1.1 jdolecek * may be used to endorse or promote products derived from this software 48 1.1 jdolecek * without specific prior written permission. 49 1.1 jdolecek * 50 1.1 jdolecek * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 51 1.1 jdolecek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52 1.1 jdolecek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53 1.1 jdolecek * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 54 1.1 jdolecek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 55 1.1 jdolecek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 56 1.1 jdolecek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 57 1.1 jdolecek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 58 1.1 jdolecek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 59 1.1 jdolecek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 60 1.1 jdolecek * THE POSSIBILITY OF SUCH DAMAGE. 61 1.1 jdolecek * 62 1.1 jdolecek * $FreeBSD: /c/ncvs/src/sys/pci/if_sk.c,v 1.20 2000/04/22 02:16:37 wpaul Exp $ 63 1.1 jdolecek */ 64 1.1 jdolecek 65 1.1 jdolecek /* 66 1.1 jdolecek * Copyright (c) 2003 Nathan L. Binkert <binkertn (at) umich.edu> 67 1.1 jdolecek * 68 1.1 jdolecek * Permission to use, copy, modify, and distribute this software for any 69 1.1 jdolecek * purpose with or without fee is hereby granted, provided that the above 70 1.1 jdolecek * copyright notice and this permission notice appear in all copies. 71 1.1 jdolecek * 72 1.1 jdolecek * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 73 1.1 jdolecek * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 74 1.1 jdolecek * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 75 1.1 jdolecek * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 76 1.1 jdolecek * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 77 1.1 jdolecek * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 78 1.1 jdolecek * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 79 1.1 jdolecek */ 80 1.1 jdolecek 81 1.1 jdolecek /* 82 1.1 jdolecek * SysKonnect SK-NET gigabit ethernet driver for FreeBSD. Supports 83 1.1 jdolecek * the SK-984x series adapters, both single port and dual port. 84 1.1 jdolecek * References: 85 1.92 msaitoh * The XaQti XMAC II datasheet, 86 1.1 jdolecek * http://www.freebsd.org/~wpaul/SysKonnect/xmacii_datasheet_rev_c_9-29.pdf 87 1.1 jdolecek * The SysKonnect GEnesis manual, http://www.syskonnect.com 88 1.1 jdolecek * 89 1.1 jdolecek * Note: XaQti has been acquired by Vitesse, and Vitesse does not have the 90 1.1 jdolecek * XMAC II datasheet online. I have put my copy at people.freebsd.org as a 91 1.1 jdolecek * convenience to others until Vitesse corrects this problem: 92 1.1 jdolecek * 93 1.1 jdolecek * http://people.freebsd.org/~wpaul/SysKonnect/xmacii_datasheet_rev_c_9-29.pdf 94 1.1 jdolecek * 95 1.1 jdolecek * Written by Bill Paul <wpaul (at) ee.columbia.edu> 96 1.1 jdolecek * Department of Electrical Engineering 97 1.1 jdolecek * Columbia University, New York City 98 1.1 jdolecek */ 99 1.1 jdolecek 100 1.1 jdolecek /* 101 1.1 jdolecek * The SysKonnect gigabit ethernet adapters consist of two main 102 1.1 jdolecek * components: the SysKonnect GEnesis controller chip and the XaQti Corp. 103 1.1 jdolecek * XMAC II gigabit ethernet MAC. The XMAC provides all of the MAC 104 1.1 jdolecek * components and a PHY while the GEnesis controller provides a PCI 105 1.1 jdolecek * interface with DMA support. Each card may have between 512K and 106 1.1 jdolecek * 2MB of SRAM on board depending on the configuration. 107 1.1 jdolecek * 108 1.1 jdolecek * The SysKonnect GEnesis controller can have either one or two XMAC 109 1.1 jdolecek * chips connected to it, allowing single or dual port NIC configurations. 110 1.1 jdolecek * SysKonnect has the distinction of being the only vendor on the market 111 1.1 jdolecek * with a dual port gigabit ethernet NIC. The GEnesis provides dual FIFOs, 112 1.1 jdolecek * dual DMA queues, packet/MAC/transmit arbiters and direct access to the 113 1.1 jdolecek * XMAC registers. This driver takes advantage of these features to allow 114 1.1 jdolecek * both XMACs to operate as independent interfaces. 115 1.1 jdolecek */ 116 1.14 perry 117 1.42 dsl #include <sys/cdefs.h> 118 1.113 rin __KERNEL_RCSID(0, "$NetBSD: if_sk.c,v 1.113 2024/07/05 04:31:51 rin Exp $"); 119 1.1 jdolecek 120 1.1 jdolecek #include <sys/param.h> 121 1.1 jdolecek #include <sys/systm.h> 122 1.1 jdolecek #include <sys/sockio.h> 123 1.1 jdolecek #include <sys/mbuf.h> 124 1.1 jdolecek #include <sys/malloc.h> 125 1.50 cube #include <sys/mutex.h> 126 1.1 jdolecek #include <sys/kernel.h> 127 1.1 jdolecek #include <sys/socket.h> 128 1.1 jdolecek #include <sys/device.h> 129 1.1 jdolecek #include <sys/queue.h> 130 1.1 jdolecek #include <sys/callout.h> 131 1.20 riz #include <sys/sysctl.h> 132 1.29 riz #include <sys/endian.h> 133 1.1 jdolecek 134 1.1 jdolecek #include <net/if.h> 135 1.1 jdolecek #include <net/if_dl.h> 136 1.1 jdolecek #include <net/if_types.h> 137 1.1 jdolecek 138 1.1 jdolecek #include <net/if_media.h> 139 1.1 jdolecek 140 1.1 jdolecek #include <net/bpf.h> 141 1.80 riastrad #include <sys/rndsource.h> 142 1.1 jdolecek 143 1.1 jdolecek #include <dev/mii/mii.h> 144 1.1 jdolecek #include <dev/mii/miivar.h> 145 1.1 jdolecek #include <dev/mii/brgphyreg.h> 146 1.1 jdolecek 147 1.1 jdolecek #include <dev/pci/pcireg.h> 148 1.1 jdolecek #include <dev/pci/pcivar.h> 149 1.1 jdolecek #include <dev/pci/pcidevs.h> 150 1.1 jdolecek 151 1.1 jdolecek /* #define SK_USEIOSPACE */ 152 1.1 jdolecek 153 1.1 jdolecek #include <dev/pci/if_skreg.h> 154 1.1 jdolecek #include <dev/pci/if_skvar.h> 155 1.1 jdolecek 156 1.102 maxv static int skc_probe(device_t, cfdata_t, void *); 157 1.102 maxv static void skc_attach(device_t, device_t, void *); 158 1.102 maxv static int sk_probe(device_t, cfdata_t, void *); 159 1.102 maxv static void sk_attach(device_t, device_t, void *); 160 1.102 maxv static int skcprint(void *, const char *); 161 1.102 maxv static int sk_intr(void *); 162 1.102 maxv static void sk_intr_bcom(struct sk_if_softc *); 163 1.102 maxv static void sk_intr_xmac(struct sk_if_softc *); 164 1.102 maxv static void sk_intr_yukon(struct sk_if_softc *); 165 1.102 maxv static void sk_rxeof(struct sk_if_softc *); 166 1.102 maxv static void sk_txeof(struct sk_if_softc *); 167 1.102 maxv static int sk_encap(struct sk_if_softc *, struct mbuf *, uint32_t *); 168 1.102 maxv static void sk_start(struct ifnet *); 169 1.102 maxv static int sk_ioctl(struct ifnet *, u_long, void *); 170 1.102 maxv static int sk_init(struct ifnet *); 171 1.102 maxv static void sk_unreset_xmac(struct sk_if_softc *); 172 1.102 maxv static void sk_init_xmac(struct sk_if_softc *); 173 1.102 maxv static void sk_unreset_yukon(struct sk_if_softc *); 174 1.102 maxv static void sk_init_yukon(struct sk_if_softc *); 175 1.102 maxv static void sk_stop(struct ifnet *, int); 176 1.102 maxv static void sk_watchdog(struct ifnet *); 177 1.102 maxv static int sk_ifmedia_upd(struct ifnet *); 178 1.102 maxv static void sk_reset(struct sk_softc *); 179 1.102 maxv static int sk_newbuf(struct sk_if_softc *, int, struct mbuf *, bus_dmamap_t); 180 1.102 maxv static int sk_alloc_jumbo_mem(struct sk_if_softc *); 181 1.102 maxv static void *sk_jalloc(struct sk_if_softc *); 182 1.102 maxv static void sk_jfree(struct mbuf *, void *, size_t, void *); 183 1.102 maxv static int sk_init_rx_ring(struct sk_if_softc *); 184 1.102 maxv static int sk_init_tx_ring(struct sk_if_softc *); 185 1.102 maxv static uint8_t sk_vpd_readbyte(struct sk_softc *, int); 186 1.102 maxv static void sk_vpd_read_res(struct sk_softc *, struct vpd_res *, int); 187 1.102 maxv static void sk_vpd_read(struct sk_softc *); 188 1.102 maxv 189 1.102 maxv static void sk_update_int_mod(struct sk_softc *); 190 1.102 maxv 191 1.102 maxv static int sk_xmac_miibus_readreg(device_t, int, int, uint16_t *); 192 1.102 maxv static int sk_xmac_miibus_writereg(device_t, int, int, uint16_t); 193 1.102 maxv static void sk_xmac_miibus_statchg(struct ifnet *); 194 1.102 maxv 195 1.102 maxv static int sk_marv_miibus_readreg(device_t, int, int, uint16_t *); 196 1.102 maxv static int sk_marv_miibus_writereg(device_t, int, int, uint16_t); 197 1.102 maxv static void sk_marv_miibus_statchg(struct ifnet *); 198 1.102 maxv 199 1.102 maxv static uint32_t sk_xmac_hash(void *); 200 1.102 maxv static uint32_t sk_yukon_hash(void *); 201 1.102 maxv static void sk_setfilt(struct sk_if_softc *, void *, int); 202 1.102 maxv static void sk_setmulti(struct sk_if_softc *); 203 1.102 maxv static void sk_tick(void *); 204 1.1 jdolecek 205 1.65 dyoung static bool skc_suspend(device_t, const pmf_qual_t *); 206 1.65 dyoung static bool skc_resume(device_t, const pmf_qual_t *); 207 1.65 dyoung static bool sk_resume(device_t dv, const pmf_qual_t *); 208 1.60 kefren 209 1.1 jdolecek /* #define SK_DEBUG 2 */ 210 1.1 jdolecek #ifdef SK_DEBUG 211 1.1 jdolecek #define DPRINTF(x) if (skdebug) printf x 212 1.96 msaitoh #define DPRINTFN(n, x) if (skdebug >= (n)) printf x 213 1.1 jdolecek int skdebug = SK_DEBUG; 214 1.1 jdolecek 215 1.102 maxv static void sk_dump_txdesc(struct sk_tx_desc *, int); 216 1.102 maxv static void sk_dump_mbuf(struct mbuf *); 217 1.102 maxv static void sk_dump_bytes(const char *, int); 218 1.1 jdolecek #else 219 1.1 jdolecek #define DPRINTF(x) 220 1.96 msaitoh #define DPRINTFN(n, x) 221 1.1 jdolecek #endif 222 1.1 jdolecek 223 1.20 riz static int sk_sysctl_handler(SYSCTLFN_PROTO); 224 1.20 riz static int sk_root_num; 225 1.20 riz 226 1.1 jdolecek /* supported device vendors */ 227 1.39 briggs /* PCI_PRODUCT_DLINK_DGE560T_2 might belong in if_msk instead */ 228 1.108 thorpej static const struct device_compatible_entry compat_data[] = { 229 1.108 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_3COM, 230 1.108 thorpej PCI_PRODUCT_3COM_3C940) }, 231 1.108 thorpej 232 1.108 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_DLINK, 233 1.108 thorpej PCI_PRODUCT_DLINK_DGE530T) }, 234 1.108 thorpej 235 1.108 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_DLINK, 236 1.108 thorpej PCI_PRODUCT_DLINK_DGE560T_2) }, 237 1.108 thorpej 238 1.108 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_LINKSYS, 239 1.108 thorpej PCI_PRODUCT_LINKSYS_EG1064) }, 240 1.108 thorpej 241 1.108 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_SCHNEIDERKOCH, 242 1.108 thorpej PCI_PRODUCT_SCHNEIDERKOCH_SKNET_GE) }, 243 1.108 thorpej 244 1.108 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_SCHNEIDERKOCH, 245 1.108 thorpej PCI_PRODUCT_SCHNEIDERKOCH_SK9821v2) }, 246 1.108 thorpej 247 1.108 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 248 1.108 thorpej PCI_PRODUCT_MARVELL_SKNET) }, 249 1.108 thorpej 250 1.108 thorpej { .id = PCI_ID_CODE(PCI_VENDOR_MARVELL, 251 1.108 thorpej PCI_PRODUCT_MARVELL_BELKIN) }, 252 1.108 thorpej 253 1.108 thorpej PCI_COMPAT_EOL 254 1.1 jdolecek }; 255 1.1 jdolecek 256 1.18 riz #define SK_LINKSYS_EG1032_SUBID 0x00151737 257 1.18 riz 258 1.91 msaitoh static inline uint32_t 259 1.91 msaitoh sk_win_read_4(struct sk_softc *sc, uint32_t reg) 260 1.1 jdolecek { 261 1.1 jdolecek #ifdef SK_USEIOSPACE 262 1.1 jdolecek CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg)); 263 1.1 jdolecek return CSR_READ_4(sc, SK_WIN_BASE + SK_REG(reg)); 264 1.1 jdolecek #else 265 1.1 jdolecek return CSR_READ_4(sc, reg); 266 1.1 jdolecek #endif 267 1.1 jdolecek } 268 1.1 jdolecek 269 1.91 msaitoh static inline uint16_t 270 1.91 msaitoh sk_win_read_2(struct sk_softc *sc, uint32_t reg) 271 1.1 jdolecek { 272 1.1 jdolecek #ifdef SK_USEIOSPACE 273 1.1 jdolecek CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg)); 274 1.1 jdolecek return CSR_READ_2(sc, SK_WIN_BASE + SK_REG(reg)); 275 1.1 jdolecek #else 276 1.1 jdolecek return CSR_READ_2(sc, reg); 277 1.1 jdolecek #endif 278 1.1 jdolecek } 279 1.1 jdolecek 280 1.91 msaitoh static inline uint8_t 281 1.91 msaitoh sk_win_read_1(struct sk_softc *sc, uint32_t reg) 282 1.1 jdolecek { 283 1.1 jdolecek #ifdef SK_USEIOSPACE 284 1.1 jdolecek CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg)); 285 1.1 jdolecek return CSR_READ_1(sc, SK_WIN_BASE + SK_REG(reg)); 286 1.1 jdolecek #else 287 1.1 jdolecek return CSR_READ_1(sc, reg); 288 1.1 jdolecek #endif 289 1.1 jdolecek } 290 1.1 jdolecek 291 1.1 jdolecek static inline void 292 1.91 msaitoh sk_win_write_4(struct sk_softc *sc, uint32_t reg, uint32_t x) 293 1.1 jdolecek { 294 1.1 jdolecek #ifdef SK_USEIOSPACE 295 1.1 jdolecek CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg)); 296 1.1 jdolecek CSR_WRITE_4(sc, SK_WIN_BASE + SK_REG(reg), x); 297 1.1 jdolecek #else 298 1.1 jdolecek CSR_WRITE_4(sc, reg, x); 299 1.1 jdolecek #endif 300 1.1 jdolecek } 301 1.1 jdolecek 302 1.1 jdolecek static inline void 303 1.91 msaitoh sk_win_write_2(struct sk_softc *sc, uint32_t reg, uint16_t x) 304 1.1 jdolecek { 305 1.1 jdolecek #ifdef SK_USEIOSPACE 306 1.1 jdolecek CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg)); 307 1.1 jdolecek CSR_WRITE_2(sc, SK_WIN_BASE + SK_REG(reg), x); 308 1.1 jdolecek #else 309 1.1 jdolecek CSR_WRITE_2(sc, reg, x); 310 1.1 jdolecek #endif 311 1.1 jdolecek } 312 1.1 jdolecek 313 1.1 jdolecek static inline void 314 1.91 msaitoh sk_win_write_1(struct sk_softc *sc, uint32_t reg, uint8_t x) 315 1.1 jdolecek { 316 1.1 jdolecek #ifdef SK_USEIOSPACE 317 1.1 jdolecek CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg)); 318 1.1 jdolecek CSR_WRITE_1(sc, SK_WIN_BASE + SK_REG(reg), x); 319 1.1 jdolecek #else 320 1.1 jdolecek CSR_WRITE_1(sc, reg, x); 321 1.1 jdolecek #endif 322 1.1 jdolecek } 323 1.1 jdolecek 324 1.1 jdolecek /* 325 1.1 jdolecek * The VPD EEPROM contains Vital Product Data, as suggested in 326 1.112 andvar * the PCI 2.1 specification. The VPD data is separated into areas 327 1.1 jdolecek * denoted by resource IDs. The SysKonnect VPD contains an ID string 328 1.1 jdolecek * resource (the name of the adapter), a read-only area resource 329 1.1 jdolecek * containing various key/data fields and a read/write area which 330 1.1 jdolecek * can be used to store asset management information or log messages. 331 1.1 jdolecek * We read the ID string and read-only into buffers attached to 332 1.1 jdolecek * the controller softc structure for later use. At the moment, 333 1.1 jdolecek * we only use the ID string during sk_attach(). 334 1.1 jdolecek */ 335 1.102 maxv static uint8_t 336 1.1 jdolecek sk_vpd_readbyte(struct sk_softc *sc, int addr) 337 1.1 jdolecek { 338 1.1 jdolecek int i; 339 1.1 jdolecek 340 1.1 jdolecek sk_win_write_2(sc, SK_PCI_REG(SK_PCI_VPD_ADDR), addr); 341 1.1 jdolecek for (i = 0; i < SK_TIMEOUT; i++) { 342 1.1 jdolecek DELAY(1); 343 1.1 jdolecek if (sk_win_read_2(sc, 344 1.1 jdolecek SK_PCI_REG(SK_PCI_VPD_ADDR)) & SK_VPD_FLAG) 345 1.1 jdolecek break; 346 1.1 jdolecek } 347 1.1 jdolecek 348 1.1 jdolecek if (i == SK_TIMEOUT) 349 1.31 riz return 0; 350 1.1 jdolecek 351 1.31 riz return sk_win_read_1(sc, SK_PCI_REG(SK_PCI_VPD_DATA)); 352 1.1 jdolecek } 353 1.1 jdolecek 354 1.102 maxv static void 355 1.1 jdolecek sk_vpd_read_res(struct sk_softc *sc, struct vpd_res *res, int addr) 356 1.1 jdolecek { 357 1.1 jdolecek int i; 358 1.91 msaitoh uint8_t *ptr; 359 1.1 jdolecek 360 1.91 msaitoh ptr = (uint8_t *)res; 361 1.1 jdolecek for (i = 0; i < sizeof(struct vpd_res); i++) 362 1.1 jdolecek ptr[i] = sk_vpd_readbyte(sc, i + addr); 363 1.1 jdolecek } 364 1.1 jdolecek 365 1.102 maxv static void 366 1.1 jdolecek sk_vpd_read(struct sk_softc *sc) 367 1.1 jdolecek { 368 1.1 jdolecek int pos = 0, i; 369 1.1 jdolecek struct vpd_res res; 370 1.1 jdolecek 371 1.1 jdolecek if (sc->sk_vpd_prodname != NULL) 372 1.1 jdolecek free(sc->sk_vpd_prodname, M_DEVBUF); 373 1.1 jdolecek if (sc->sk_vpd_readonly != NULL) 374 1.1 jdolecek free(sc->sk_vpd_readonly, M_DEVBUF); 375 1.1 jdolecek sc->sk_vpd_prodname = NULL; 376 1.1 jdolecek sc->sk_vpd_readonly = NULL; 377 1.1 jdolecek 378 1.1 jdolecek sk_vpd_read_res(sc, &res, pos); 379 1.1 jdolecek 380 1.1 jdolecek if (res.vr_id != VPD_RES_ID) { 381 1.51 christos aprint_error_dev(sc->sk_dev, 382 1.51 christos "bad VPD resource id: expected %x got %x\n", 383 1.48 cegger VPD_RES_ID, res.vr_id); 384 1.1 jdolecek return; 385 1.1 jdolecek } 386 1.1 jdolecek 387 1.1 jdolecek pos += sizeof(res); 388 1.101 chs sc->sk_vpd_prodname = malloc(res.vr_len + 1, M_DEVBUF, M_WAITOK); 389 1.1 jdolecek for (i = 0; i < res.vr_len; i++) 390 1.1 jdolecek sc->sk_vpd_prodname[i] = sk_vpd_readbyte(sc, i + pos); 391 1.1 jdolecek sc->sk_vpd_prodname[i] = '\0'; 392 1.1 jdolecek pos += i; 393 1.1 jdolecek 394 1.1 jdolecek sk_vpd_read_res(sc, &res, pos); 395 1.1 jdolecek 396 1.1 jdolecek if (res.vr_id != VPD_RES_READ) { 397 1.51 christos aprint_error_dev(sc->sk_dev, 398 1.51 christos "bad VPD resource id: expected %x got %x\n", 399 1.48 cegger VPD_RES_READ, res.vr_id); 400 1.1 jdolecek return; 401 1.1 jdolecek } 402 1.1 jdolecek 403 1.1 jdolecek pos += sizeof(res); 404 1.101 chs sc->sk_vpd_readonly = malloc(res.vr_len, M_DEVBUF, M_WAITOK); 405 1.11 skd for (i = 0; i < res.vr_len ; i++) 406 1.1 jdolecek sc->sk_vpd_readonly[i] = sk_vpd_readbyte(sc, i + pos); 407 1.1 jdolecek } 408 1.1 jdolecek 409 1.102 maxv static int 410 1.93 msaitoh sk_xmac_miibus_readreg(device_t dev, int phy, int reg, uint16_t *val) 411 1.1 jdolecek { 412 1.53 christos struct sk_if_softc *sc_if = device_private(dev); 413 1.1 jdolecek int i; 414 1.1 jdolecek 415 1.1 jdolecek DPRINTFN(9, ("sk_xmac_miibus_readreg\n")); 416 1.1 jdolecek 417 1.1 jdolecek if (sc_if->sk_phytype == SK_PHYTYPE_XMAC && phy != 0) 418 1.93 msaitoh return -1; 419 1.1 jdolecek 420 1.1 jdolecek SK_XM_WRITE_2(sc_if, XM_PHY_ADDR, reg|(phy << 8)); 421 1.1 jdolecek SK_XM_READ_2(sc_if, XM_PHY_DATA); 422 1.1 jdolecek if (sc_if->sk_phytype != SK_PHYTYPE_XMAC) { 423 1.1 jdolecek for (i = 0; i < SK_TIMEOUT; i++) { 424 1.1 jdolecek DELAY(1); 425 1.1 jdolecek if (SK_XM_READ_2(sc_if, XM_MMUCMD) & 426 1.1 jdolecek XM_MMUCMD_PHYDATARDY) 427 1.1 jdolecek break; 428 1.1 jdolecek } 429 1.1 jdolecek 430 1.1 jdolecek if (i == SK_TIMEOUT) { 431 1.51 christos aprint_error_dev(sc_if->sk_dev, 432 1.51 christos "phy failed to come ready\n"); 433 1.93 msaitoh return ETIMEDOUT; 434 1.1 jdolecek } 435 1.1 jdolecek } 436 1.1 jdolecek DELAY(1); 437 1.93 msaitoh *val = SK_XM_READ_2(sc_if, XM_PHY_DATA); 438 1.93 msaitoh return 0; 439 1.1 jdolecek } 440 1.1 jdolecek 441 1.102 maxv static int 442 1.93 msaitoh sk_xmac_miibus_writereg(device_t dev, int phy, int reg, uint16_t val) 443 1.1 jdolecek { 444 1.53 christos struct sk_if_softc *sc_if = device_private(dev); 445 1.1 jdolecek int i; 446 1.1 jdolecek 447 1.1 jdolecek DPRINTFN(9, ("sk_xmac_miibus_writereg\n")); 448 1.1 jdolecek 449 1.1 jdolecek SK_XM_WRITE_2(sc_if, XM_PHY_ADDR, reg|(phy << 8)); 450 1.1 jdolecek for (i = 0; i < SK_TIMEOUT; i++) { 451 1.1 jdolecek if (!(SK_XM_READ_2(sc_if, XM_MMUCMD) & XM_MMUCMD_PHYBUSY)) 452 1.1 jdolecek break; 453 1.1 jdolecek } 454 1.1 jdolecek 455 1.1 jdolecek if (i == SK_TIMEOUT) { 456 1.51 christos aprint_error_dev(sc_if->sk_dev, "phy failed to come ready\n"); 457 1.93 msaitoh return ETIMEDOUT; 458 1.1 jdolecek } 459 1.1 jdolecek 460 1.1 jdolecek SK_XM_WRITE_2(sc_if, XM_PHY_DATA, val); 461 1.1 jdolecek for (i = 0; i < SK_TIMEOUT; i++) { 462 1.1 jdolecek DELAY(1); 463 1.1 jdolecek if (!(SK_XM_READ_2(sc_if, XM_MMUCMD) & XM_MMUCMD_PHYBUSY)) 464 1.1 jdolecek break; 465 1.1 jdolecek } 466 1.1 jdolecek 467 1.93 msaitoh if (i == SK_TIMEOUT) { 468 1.51 christos aprint_error_dev(sc_if->sk_dev, "phy write timed out\n"); 469 1.93 msaitoh return ETIMEDOUT; 470 1.93 msaitoh } 471 1.93 msaitoh 472 1.93 msaitoh return 0; 473 1.1 jdolecek } 474 1.1 jdolecek 475 1.102 maxv static void 476 1.72 matt sk_xmac_miibus_statchg(struct ifnet *ifp) 477 1.1 jdolecek { 478 1.72 matt struct sk_if_softc *sc_if = ifp->if_softc; 479 1.1 jdolecek struct mii_data *mii = &sc_if->sk_mii; 480 1.1 jdolecek 481 1.1 jdolecek DPRINTFN(9, ("sk_xmac_miibus_statchg\n")); 482 1.1 jdolecek 483 1.1 jdolecek /* 484 1.1 jdolecek * If this is a GMII PHY, manually set the XMAC's 485 1.1 jdolecek * duplex mode accordingly. 486 1.1 jdolecek */ 487 1.1 jdolecek if (sc_if->sk_phytype != SK_PHYTYPE_XMAC) { 488 1.95 msaitoh if ((mii->mii_media_active & IFM_FDX) != 0) 489 1.1 jdolecek SK_XM_SETBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_GMIIFDX); 490 1.31 riz else 491 1.1 jdolecek SK_XM_CLRBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_GMIIFDX); 492 1.1 jdolecek } 493 1.1 jdolecek } 494 1.1 jdolecek 495 1.102 maxv static int 496 1.93 msaitoh sk_marv_miibus_readreg(device_t dev, int phy, int reg, uint16_t *val) 497 1.1 jdolecek { 498 1.53 christos struct sk_if_softc *sc_if = device_private(dev); 499 1.93 msaitoh uint16_t data; 500 1.1 jdolecek int i; 501 1.1 jdolecek 502 1.1 jdolecek if (phy != 0 || 503 1.1 jdolecek (sc_if->sk_phytype != SK_PHYTYPE_MARV_COPPER && 504 1.1 jdolecek sc_if->sk_phytype != SK_PHYTYPE_MARV_FIBER)) { 505 1.1 jdolecek DPRINTFN(9, ("sk_marv_miibus_readreg (skip) phy=%d, reg=%#x\n", 506 1.1 jdolecek phy, reg)); 507 1.93 msaitoh return -1; 508 1.1 jdolecek } 509 1.1 jdolecek 510 1.92 msaitoh SK_YU_WRITE_2(sc_if, YUKON_SMICR, YU_SMICR_PHYAD(phy) | 511 1.1 jdolecek YU_SMICR_REGAD(reg) | YU_SMICR_OP_READ); 512 1.14 perry 513 1.1 jdolecek for (i = 0; i < SK_TIMEOUT; i++) { 514 1.1 jdolecek DELAY(1); 515 1.93 msaitoh data = SK_YU_READ_2(sc_if, YUKON_SMICR); 516 1.93 msaitoh if (data & YU_SMICR_READ_VALID) 517 1.1 jdolecek break; 518 1.1 jdolecek } 519 1.1 jdolecek 520 1.1 jdolecek if (i == SK_TIMEOUT) { 521 1.51 christos aprint_error_dev(sc_if->sk_dev, "phy failed to come ready\n"); 522 1.93 msaitoh return ETIMEDOUT; 523 1.1 jdolecek } 524 1.14 perry 525 1.92 msaitoh DPRINTFN(9, ("sk_marv_miibus_readreg: i=%d, timeout=%d\n", i, 526 1.1 jdolecek SK_TIMEOUT)); 527 1.1 jdolecek 528 1.93 msaitoh *val = SK_YU_READ_2(sc_if, YUKON_SMIDR); 529 1.1 jdolecek 530 1.93 msaitoh DPRINTFN(9, ("sk_marv_miibus_readreg phy=%d, reg=%#x, val=%#hx\n", 531 1.93 msaitoh phy, reg, *val)); 532 1.1 jdolecek 533 1.93 msaitoh return 0; 534 1.1 jdolecek } 535 1.1 jdolecek 536 1.102 maxv static int 537 1.93 msaitoh sk_marv_miibus_writereg(device_t dev, int phy, int reg, uint16_t val) 538 1.1 jdolecek { 539 1.51 christos struct sk_if_softc *sc_if = device_private(dev); 540 1.1 jdolecek int i; 541 1.1 jdolecek 542 1.93 msaitoh DPRINTFN(9, ("sk_marv_miibus_writereg phy=%d reg=%#x val=%#hx\n", 543 1.1 jdolecek phy, reg, val)); 544 1.1 jdolecek 545 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_SMIDR, val); 546 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_SMICR, YU_SMICR_PHYAD(phy) | 547 1.1 jdolecek YU_SMICR_REGAD(reg) | YU_SMICR_OP_WRITE); 548 1.1 jdolecek 549 1.1 jdolecek for (i = 0; i < SK_TIMEOUT; i++) { 550 1.1 jdolecek DELAY(1); 551 1.38 msaitoh if (!(SK_YU_READ_2(sc_if, YUKON_SMICR) & YU_SMICR_BUSY)) 552 1.1 jdolecek break; 553 1.1 jdolecek } 554 1.38 msaitoh 555 1.93 msaitoh if (i == SK_TIMEOUT) { 556 1.51 christos printf("%s: phy write timed out\n", 557 1.51 christos device_xname(sc_if->sk_dev)); 558 1.93 msaitoh return ETIMEDOUT; 559 1.93 msaitoh } 560 1.93 msaitoh 561 1.93 msaitoh return 0; 562 1.1 jdolecek } 563 1.1 jdolecek 564 1.102 maxv static void 565 1.72 matt sk_marv_miibus_statchg(struct ifnet *ifp) 566 1.1 jdolecek { 567 1.1 jdolecek DPRINTFN(9, ("sk_marv_miibus_statchg: gpcr=%x\n", 568 1.72 matt SK_YU_READ_2(((struct sk_if_softc *)ifp->if_softc), 569 1.54 cegger YUKON_GPCR))); 570 1.1 jdolecek } 571 1.1 jdolecek 572 1.102 maxv static uint32_t 573 1.37 christos sk_xmac_hash(void *addr) 574 1.1 jdolecek { 575 1.91 msaitoh uint32_t crc; 576 1.1 jdolecek 577 1.96 msaitoh crc = ether_crc32_le(addr, ETHER_ADDR_LEN); 578 1.14 perry crc = ~crc & ((1<< SK_HASH_BITS) - 1); 579 1.96 msaitoh DPRINTFN(2,("multicast hash for %s is %x\n", ether_sprintf(addr),crc)); 580 1.31 riz return crc; 581 1.8 kleink } 582 1.8 kleink 583 1.102 maxv static uint32_t 584 1.37 christos sk_yukon_hash(void *addr) 585 1.8 kleink { 586 1.91 msaitoh uint32_t crc; 587 1.8 kleink 588 1.96 msaitoh crc = ether_crc32_be(addr, ETHER_ADDR_LEN); 589 1.8 kleink crc &= ((1 << SK_HASH_BITS) - 1); 590 1.96 msaitoh DPRINTFN(2,("multicast hash for %s is %x\n", ether_sprintf(addr),crc)); 591 1.31 riz return crc; 592 1.1 jdolecek } 593 1.1 jdolecek 594 1.102 maxv static void 595 1.37 christos sk_setfilt(struct sk_if_softc *sc_if, void *addrv, int slot) 596 1.1 jdolecek { 597 1.37 christos char *addr = addrv; 598 1.1 jdolecek int base = XM_RXFILT_ENTRY(slot); 599 1.1 jdolecek 600 1.91 msaitoh SK_XM_WRITE_2(sc_if, base, *(uint16_t *)(&addr[0])); 601 1.91 msaitoh SK_XM_WRITE_2(sc_if, base + 2, *(uint16_t *)(&addr[2])); 602 1.91 msaitoh SK_XM_WRITE_2(sc_if, base + 4, *(uint16_t *)(&addr[4])); 603 1.1 jdolecek } 604 1.1 jdolecek 605 1.102 maxv static void 606 1.1 jdolecek sk_setmulti(struct sk_if_softc *sc_if) 607 1.1 jdolecek { 608 1.1 jdolecek struct sk_softc *sc = sc_if->sk_softc; 609 1.1 jdolecek struct ifnet *ifp= &sc_if->sk_ethercom.ec_if; 610 1.91 msaitoh uint32_t hashes[2] = { 0, 0 }; 611 1.8 kleink int h = 0, i; 612 1.1 jdolecek struct ethercom *ec = &sc_if->sk_ethercom; 613 1.1 jdolecek struct ether_multi *enm; 614 1.1 jdolecek struct ether_multistep step; 615 1.96 msaitoh uint8_t dummy[] = { 0, 0, 0, 0, 0, 0 }; 616 1.1 jdolecek 617 1.1 jdolecek /* First, zot all the existing filters. */ 618 1.31 riz switch (sc->sk_type) { 619 1.1 jdolecek case SK_GENESIS: 620 1.1 jdolecek for (i = 1; i < XM_RXFILT_MAX; i++) 621 1.37 christos sk_setfilt(sc_if, (void *)&dummy, i); 622 1.1 jdolecek 623 1.1 jdolecek SK_XM_WRITE_4(sc_if, XM_MAR0, 0); 624 1.1 jdolecek SK_XM_WRITE_4(sc_if, XM_MAR2, 0); 625 1.1 jdolecek break; 626 1.1 jdolecek case SK_YUKON: 627 1.11 skd case SK_YUKON_LITE: 628 1.11 skd case SK_YUKON_LP: 629 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_MCAH1, 0); 630 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_MCAH2, 0); 631 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_MCAH3, 0); 632 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_MCAH4, 0); 633 1.1 jdolecek break; 634 1.1 jdolecek } 635 1.1 jdolecek 636 1.1 jdolecek /* Now program new ones. */ 637 1.1 jdolecek allmulti: 638 1.1 jdolecek if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 639 1.1 jdolecek hashes[0] = 0xFFFFFFFF; 640 1.1 jdolecek hashes[1] = 0xFFFFFFFF; 641 1.1 jdolecek } else { 642 1.1 jdolecek i = 1; 643 1.1 jdolecek /* First find the tail of the list. */ 644 1.97 msaitoh ETHER_LOCK(ec); 645 1.1 jdolecek ETHER_FIRST_MULTI(step, ec, enm); 646 1.1 jdolecek while (enm != NULL) { 647 1.58 cegger if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 648 1.1 jdolecek ETHER_ADDR_LEN)) { 649 1.1 jdolecek ifp->if_flags |= IFF_ALLMULTI; 650 1.97 msaitoh ETHER_UNLOCK(ec); 651 1.1 jdolecek goto allmulti; 652 1.1 jdolecek } 653 1.1 jdolecek DPRINTFN(2,("multicast address %s\n", 654 1.92 msaitoh ether_sprintf(enm->enm_addrlo))); 655 1.1 jdolecek /* 656 1.1 jdolecek * Program the first XM_RXFILT_MAX multicast groups 657 1.1 jdolecek * into the perfect filter. For all others, 658 1.1 jdolecek * use the hash table. 659 1.1 jdolecek */ 660 1.1 jdolecek if (sc->sk_type == SK_GENESIS && i < XM_RXFILT_MAX) { 661 1.1 jdolecek sk_setfilt(sc_if, enm->enm_addrlo, i); 662 1.1 jdolecek i++; 663 1.1 jdolecek } 664 1.1 jdolecek else { 665 1.8 kleink switch (sc->sk_type) { 666 1.8 kleink case SK_GENESIS: 667 1.8 kleink h = sk_xmac_hash(enm->enm_addrlo); 668 1.8 kleink break; 669 1.8 kleink case SK_YUKON: 670 1.11 skd case SK_YUKON_LITE: 671 1.11 skd case SK_YUKON_LP: 672 1.8 kleink h = sk_yukon_hash(enm->enm_addrlo); 673 1.8 kleink break; 674 1.8 kleink } 675 1.1 jdolecek if (h < 32) 676 1.1 jdolecek hashes[0] |= (1 << h); 677 1.1 jdolecek else 678 1.1 jdolecek hashes[1] |= (1 << (h - 32)); 679 1.1 jdolecek } 680 1.1 jdolecek 681 1.1 jdolecek ETHER_NEXT_MULTI(step, enm); 682 1.1 jdolecek } 683 1.97 msaitoh ETHER_UNLOCK(ec); 684 1.1 jdolecek } 685 1.1 jdolecek 686 1.31 riz switch (sc->sk_type) { 687 1.1 jdolecek case SK_GENESIS: 688 1.96 msaitoh SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_USE_HASH | 689 1.1 jdolecek XM_MODE_RX_USE_PERFECT); 690 1.1 jdolecek SK_XM_WRITE_4(sc_if, XM_MAR0, hashes[0]); 691 1.1 jdolecek SK_XM_WRITE_4(sc_if, XM_MAR2, hashes[1]); 692 1.1 jdolecek break; 693 1.1 jdolecek case SK_YUKON: 694 1.11 skd case SK_YUKON_LITE: 695 1.11 skd case SK_YUKON_LP: 696 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_MCAH1, hashes[0] & 0xffff); 697 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_MCAH2, (hashes[0] >> 16) & 0xffff); 698 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_MCAH3, hashes[1] & 0xffff); 699 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_MCAH4, (hashes[1] >> 16) & 0xffff); 700 1.1 jdolecek break; 701 1.1 jdolecek } 702 1.1 jdolecek } 703 1.1 jdolecek 704 1.102 maxv static int 705 1.1 jdolecek sk_init_rx_ring(struct sk_if_softc *sc_if) 706 1.1 jdolecek { 707 1.1 jdolecek struct sk_chain_data *cd = &sc_if->sk_cdata; 708 1.1 jdolecek struct sk_ring_data *rd = sc_if->sk_rdata; 709 1.1 jdolecek int i; 710 1.1 jdolecek 711 1.59 cegger memset((char *)rd->sk_rx_ring, 0, 712 1.1 jdolecek sizeof(struct sk_rx_desc) * SK_RX_RING_CNT); 713 1.1 jdolecek 714 1.1 jdolecek for (i = 0; i < SK_RX_RING_CNT; i++) { 715 1.1 jdolecek cd->sk_rx_chain[i].sk_desc = &rd->sk_rx_ring[i]; 716 1.1 jdolecek if (i == (SK_RX_RING_CNT - 1)) { 717 1.1 jdolecek cd->sk_rx_chain[i].sk_next = &cd->sk_rx_chain[0]; 718 1.29 riz rd->sk_rx_ring[i].sk_next = 719 1.29 riz htole32(SK_RX_RING_ADDR(sc_if, 0)); 720 1.1 jdolecek } else { 721 1.1 jdolecek cd->sk_rx_chain[i].sk_next = &cd->sk_rx_chain[i + 1]; 722 1.29 riz rd->sk_rx_ring[i].sk_next = 723 1.96 msaitoh htole32(SK_RX_RING_ADDR(sc_if, i+1)); 724 1.1 jdolecek } 725 1.1 jdolecek } 726 1.1 jdolecek 727 1.1 jdolecek for (i = 0; i < SK_RX_RING_CNT; i++) { 728 1.73 christos if (sk_newbuf(sc_if, i, NULL, 729 1.22 riz sc_if->sk_cdata.sk_rx_jumbo_map) == ENOBUFS) { 730 1.51 christos aprint_error_dev(sc_if->sk_dev, 731 1.51 christos "failed alloc of %dth mbuf\n", i); 732 1.31 riz return ENOBUFS; 733 1.1 jdolecek } 734 1.1 jdolecek } 735 1.1 jdolecek sc_if->sk_cdata.sk_rx_prod = 0; 736 1.1 jdolecek sc_if->sk_cdata.sk_rx_cons = 0; 737 1.1 jdolecek 738 1.31 riz return 0; 739 1.1 jdolecek } 740 1.1 jdolecek 741 1.102 maxv static int 742 1.1 jdolecek sk_init_tx_ring(struct sk_if_softc *sc_if) 743 1.1 jdolecek { 744 1.1 jdolecek struct sk_chain_data *cd = &sc_if->sk_cdata; 745 1.1 jdolecek struct sk_ring_data *rd = sc_if->sk_rdata; 746 1.1 jdolecek int i; 747 1.1 jdolecek 748 1.52 christos memset(sc_if->sk_rdata->sk_tx_ring, 0, 749 1.1 jdolecek sizeof(struct sk_tx_desc) * SK_TX_RING_CNT); 750 1.1 jdolecek 751 1.1 jdolecek for (i = 0; i < SK_TX_RING_CNT; i++) { 752 1.1 jdolecek cd->sk_tx_chain[i].sk_desc = &rd->sk_tx_ring[i]; 753 1.1 jdolecek if (i == (SK_TX_RING_CNT - 1)) { 754 1.1 jdolecek cd->sk_tx_chain[i].sk_next = &cd->sk_tx_chain[0]; 755 1.29 riz rd->sk_tx_ring[i].sk_next = 756 1.29 riz htole32(SK_TX_RING_ADDR(sc_if, 0)); 757 1.1 jdolecek } else { 758 1.1 jdolecek cd->sk_tx_chain[i].sk_next = &cd->sk_tx_chain[i + 1]; 759 1.29 riz rd->sk_tx_ring[i].sk_next = 760 1.96 msaitoh htole32(SK_TX_RING_ADDR(sc_if, i+1)); 761 1.1 jdolecek } 762 1.1 jdolecek } 763 1.1 jdolecek 764 1.1 jdolecek sc_if->sk_cdata.sk_tx_prod = 0; 765 1.1 jdolecek sc_if->sk_cdata.sk_tx_cons = 0; 766 1.1 jdolecek sc_if->sk_cdata.sk_tx_cnt = 0; 767 1.1 jdolecek 768 1.3 briggs SK_CDTXSYNC(sc_if, 0, SK_TX_RING_CNT, 769 1.96 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 770 1.3 briggs 771 1.31 riz return 0; 772 1.1 jdolecek } 773 1.1 jdolecek 774 1.102 maxv static int 775 1.1 jdolecek sk_newbuf(struct sk_if_softc *sc_if, int i, struct mbuf *m, 776 1.1 jdolecek bus_dmamap_t dmamap) 777 1.1 jdolecek { 778 1.1 jdolecek struct mbuf *m_new = NULL; 779 1.1 jdolecek struct sk_chain *c; 780 1.1 jdolecek struct sk_rx_desc *r; 781 1.1 jdolecek 782 1.22 riz if (m == NULL) { 783 1.37 christos void *buf = NULL; 784 1.1 jdolecek 785 1.1 jdolecek MGETHDR(m_new, M_DONTWAIT, MT_DATA); 786 1.1 jdolecek if (m_new == NULL) { 787 1.51 christos aprint_error_dev(sc_if->sk_dev, 788 1.51 christos "no memory for rx list -- packet dropped!\n"); 789 1.31 riz return ENOBUFS; 790 1.1 jdolecek } 791 1.1 jdolecek 792 1.1 jdolecek /* Allocate the jumbo buffer */ 793 1.22 riz buf = sk_jalloc(sc_if); 794 1.22 riz if (buf == NULL) { 795 1.1 jdolecek m_freem(m_new); 796 1.22 riz DPRINTFN(1, ("%s jumbo allocation failed -- packet " 797 1.22 riz "dropped!\n", sc_if->sk_ethercom.ec_if.if_xname)); 798 1.31 riz return ENOBUFS; 799 1.1 jdolecek } 800 1.1 jdolecek 801 1.22 riz /* Attach the buffer to the mbuf */ 802 1.22 riz m_new->m_len = m_new->m_pkthdr.len = SK_JLEN; 803 1.22 riz MEXTADD(m_new, buf, SK_JLEN, 0, sk_jfree, sc_if); 804 1.1 jdolecek 805 1.1 jdolecek } else { 806 1.1 jdolecek /* 807 1.92 msaitoh * We're re-using a previously allocated mbuf; 808 1.1 jdolecek * be sure to re-init pointers and lengths to 809 1.1 jdolecek * default values. 810 1.1 jdolecek */ 811 1.1 jdolecek m_new = m; 812 1.22 riz m_new->m_len = m_new->m_pkthdr.len = SK_JLEN; 813 1.1 jdolecek m_new->m_data = m_new->m_ext.ext_buf; 814 1.1 jdolecek } 815 1.22 riz m_adj(m_new, ETHER_ALIGN); 816 1.1 jdolecek 817 1.1 jdolecek c = &sc_if->sk_cdata.sk_rx_chain[i]; 818 1.1 jdolecek r = c->sk_desc; 819 1.1 jdolecek c->sk_mbuf = m_new; 820 1.29 riz r->sk_data_lo = htole32(dmamap->dm_segs[0].ds_addr + 821 1.22 riz (((vaddr_t)m_new->m_data 822 1.29 riz - (vaddr_t)sc_if->sk_cdata.sk_jumbo_buf))); 823 1.29 riz r->sk_ctl = htole32(SK_JLEN | SK_RXSTAT); 824 1.1 jdolecek 825 1.96 msaitoh SK_CDRXSYNC(sc_if, i, BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 826 1.3 briggs 827 1.31 riz return 0; 828 1.1 jdolecek } 829 1.1 jdolecek 830 1.1 jdolecek /* 831 1.22 riz * Memory management for jumbo frames. 832 1.22 riz */ 833 1.22 riz 834 1.102 maxv static int 835 1.22 riz sk_alloc_jumbo_mem(struct sk_if_softc *sc_if) 836 1.22 riz { 837 1.22 riz struct sk_softc *sc = sc_if->sk_softc; 838 1.37 christos char *ptr, *kva; 839 1.22 riz bus_dma_segment_t seg; 840 1.22 riz int i, rseg, state, error; 841 1.92 msaitoh struct sk_jpool_entry *entry; 842 1.22 riz 843 1.22 riz state = error = 0; 844 1.22 riz 845 1.22 riz /* Grab a big chunk o' storage. */ 846 1.22 riz if (bus_dmamem_alloc(sc->sc_dmatag, SK_JMEM, PAGE_SIZE, 0, 847 1.22 riz &seg, 1, &rseg, BUS_DMA_NOWAIT)) { 848 1.51 christos aprint_error_dev(sc->sk_dev, "can't alloc rx buffers\n"); 849 1.31 riz return ENOBUFS; 850 1.22 riz } 851 1.22 riz 852 1.22 riz state = 1; 853 1.37 christos if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, SK_JMEM, (void **)&kva, 854 1.22 riz BUS_DMA_NOWAIT)) { 855 1.51 christos aprint_error_dev(sc->sk_dev, 856 1.51 christos "can't map dma buffers (%d bytes)\n", 857 1.48 cegger SK_JMEM); 858 1.22 riz error = ENOBUFS; 859 1.22 riz goto out; 860 1.22 riz } 861 1.22 riz 862 1.22 riz state = 2; 863 1.22 riz if (bus_dmamap_create(sc->sc_dmatag, SK_JMEM, 1, SK_JMEM, 0, 864 1.22 riz BUS_DMA_NOWAIT, &sc_if->sk_cdata.sk_rx_jumbo_map)) { 865 1.51 christos aprint_error_dev(sc->sk_dev, "can't create dma map\n"); 866 1.22 riz error = ENOBUFS; 867 1.22 riz goto out; 868 1.22 riz } 869 1.22 riz 870 1.22 riz state = 3; 871 1.22 riz if (bus_dmamap_load(sc->sc_dmatag, sc_if->sk_cdata.sk_rx_jumbo_map, 872 1.22 riz kva, SK_JMEM, NULL, BUS_DMA_NOWAIT)) { 873 1.51 christos aprint_error_dev(sc->sk_dev, "can't load dma map\n"); 874 1.22 riz error = ENOBUFS; 875 1.22 riz goto out; 876 1.22 riz } 877 1.22 riz 878 1.22 riz state = 4; 879 1.37 christos sc_if->sk_cdata.sk_jumbo_buf = (void *)kva; 880 1.105 rin DPRINTFN(1,("sk_jumbo_buf = %p\n", sc_if->sk_cdata.sk_jumbo_buf)); 881 1.22 riz 882 1.22 riz LIST_INIT(&sc_if->sk_jfree_listhead); 883 1.22 riz LIST_INIT(&sc_if->sk_jinuse_listhead); 884 1.50 cube mutex_init(&sc_if->sk_jpool_mtx, MUTEX_DEFAULT, IPL_NET); 885 1.22 riz 886 1.22 riz /* 887 1.22 riz * Now divide it up into 9K pieces and save the addresses 888 1.22 riz * in an array. 889 1.22 riz */ 890 1.22 riz ptr = sc_if->sk_cdata.sk_jumbo_buf; 891 1.22 riz for (i = 0; i < SK_JSLOTS; i++) { 892 1.22 riz sc_if->sk_cdata.sk_jslots[i] = ptr; 893 1.22 riz ptr += SK_JLEN; 894 1.22 riz entry = malloc(sizeof(struct sk_jpool_entry), 895 1.101 chs M_DEVBUF, M_WAITOK); 896 1.22 riz entry->slot = i; 897 1.22 riz if (i) 898 1.31 riz LIST_INSERT_HEAD(&sc_if->sk_jfree_listhead, 899 1.22 riz entry, jpool_entries); 900 1.22 riz else 901 1.31 riz LIST_INSERT_HEAD(&sc_if->sk_jinuse_listhead, 902 1.22 riz entry, jpool_entries); 903 1.22 riz } 904 1.22 riz out: 905 1.22 riz if (error != 0) { 906 1.22 riz switch (state) { 907 1.22 riz case 4: 908 1.22 riz bus_dmamap_unload(sc->sc_dmatag, 909 1.22 riz sc_if->sk_cdata.sk_rx_jumbo_map); 910 1.94 mrg /* FALLTHROUGH */ 911 1.22 riz case 3: 912 1.22 riz bus_dmamap_destroy(sc->sc_dmatag, 913 1.22 riz sc_if->sk_cdata.sk_rx_jumbo_map); 914 1.94 mrg /* FALLTHROUGH */ 915 1.22 riz case 2: 916 1.22 riz bus_dmamem_unmap(sc->sc_dmatag, kva, SK_JMEM); 917 1.94 mrg /* FALLTHROUGH */ 918 1.22 riz case 1: 919 1.22 riz bus_dmamem_free(sc->sc_dmatag, &seg, rseg); 920 1.22 riz break; 921 1.22 riz default: 922 1.22 riz break; 923 1.22 riz } 924 1.22 riz } 925 1.22 riz 926 1.31 riz return error; 927 1.22 riz } 928 1.22 riz 929 1.22 riz /* 930 1.22 riz * Allocate a jumbo buffer. 931 1.22 riz */ 932 1.102 maxv static void * 933 1.22 riz sk_jalloc(struct sk_if_softc *sc_if) 934 1.22 riz { 935 1.92 msaitoh struct sk_jpool_entry *entry; 936 1.22 riz 937 1.50 cube mutex_enter(&sc_if->sk_jpool_mtx); 938 1.22 riz entry = LIST_FIRST(&sc_if->sk_jfree_listhead); 939 1.22 riz 940 1.50 cube if (entry == NULL) { 941 1.50 cube mutex_exit(&sc_if->sk_jpool_mtx); 942 1.31 riz return NULL; 943 1.50 cube } 944 1.22 riz 945 1.22 riz LIST_REMOVE(entry, jpool_entries); 946 1.22 riz LIST_INSERT_HEAD(&sc_if->sk_jinuse_listhead, entry, jpool_entries); 947 1.50 cube mutex_exit(&sc_if->sk_jpool_mtx); 948 1.31 riz return sc_if->sk_cdata.sk_jslots[entry->slot]; 949 1.22 riz } 950 1.22 riz 951 1.22 riz /* 952 1.22 riz * Release a jumbo buffer. 953 1.22 riz */ 954 1.102 maxv static void 955 1.37 christos sk_jfree(struct mbuf *m, void *buf, size_t size, void *arg) 956 1.22 riz { 957 1.22 riz struct sk_jpool_entry *entry; 958 1.22 riz struct sk_if_softc *sc; 959 1.50 cube int i; 960 1.22 riz 961 1.22 riz /* Extract the softc struct pointer. */ 962 1.22 riz sc = (struct sk_if_softc *)arg; 963 1.22 riz 964 1.22 riz if (sc == NULL) 965 1.22 riz panic("sk_jfree: can't find softc pointer!"); 966 1.22 riz 967 1.22 riz /* calculate the slot this buffer belongs to */ 968 1.22 riz 969 1.22 riz i = ((vaddr_t)buf 970 1.22 riz - (vaddr_t)sc->sk_cdata.sk_jumbo_buf) / SK_JLEN; 971 1.22 riz 972 1.22 riz if ((i < 0) || (i >= SK_JSLOTS)) 973 1.22 riz panic("sk_jfree: asked to free buffer that we don't manage!"); 974 1.22 riz 975 1.50 cube mutex_enter(&sc->sk_jpool_mtx); 976 1.22 riz entry = LIST_FIRST(&sc->sk_jinuse_listhead); 977 1.22 riz if (entry == NULL) 978 1.22 riz panic("sk_jfree: buffer not in use!"); 979 1.22 riz entry->slot = i; 980 1.22 riz LIST_REMOVE(entry, jpool_entries); 981 1.22 riz LIST_INSERT_HEAD(&sc->sk_jfree_listhead, entry, jpool_entries); 982 1.50 cube mutex_exit(&sc->sk_jpool_mtx); 983 1.22 riz 984 1.22 riz if (__predict_true(m != NULL)) 985 1.43 ad pool_cache_put(mb_cache, m); 986 1.22 riz } 987 1.22 riz 988 1.22 riz /* 989 1.1 jdolecek * Set media options. 990 1.1 jdolecek */ 991 1.102 maxv static int 992 1.1 jdolecek sk_ifmedia_upd(struct ifnet *ifp) 993 1.1 jdolecek { 994 1.1 jdolecek struct sk_if_softc *sc_if = ifp->if_softc; 995 1.46 dyoung int rc; 996 1.1 jdolecek 997 1.1 jdolecek (void) sk_init(ifp); 998 1.46 dyoung if ((rc = mii_mediachg(&sc_if->sk_mii)) == ENXIO) 999 1.46 dyoung return 0; 1000 1.46 dyoung return rc; 1001 1.1 jdolecek } 1002 1.1 jdolecek 1003 1.84 christos static void 1004 1.84 christos sk_promisc(struct sk_if_softc *sc_if, int on) 1005 1.84 christos { 1006 1.84 christos struct sk_softc *sc = sc_if->sk_softc; 1007 1.84 christos switch (sc->sk_type) { 1008 1.84 christos case SK_GENESIS: 1009 1.84 christos if (on) 1010 1.84 christos SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_PROMISC); 1011 1.84 christos else 1012 1.84 christos SK_XM_CLRBIT_4(sc_if, XM_MODE, XM_MODE_RX_PROMISC); 1013 1.84 christos break; 1014 1.84 christos case SK_YUKON: 1015 1.84 christos case SK_YUKON_LITE: 1016 1.84 christos case SK_YUKON_LP: 1017 1.84 christos if (on) 1018 1.84 christos SK_YU_CLRBIT_2(sc_if, YUKON_RCR, 1019 1.84 christos YU_RCR_UFLEN | YU_RCR_MUFLEN); 1020 1.84 christos else 1021 1.84 christos SK_YU_SETBIT_2(sc_if, YUKON_RCR, 1022 1.84 christos YU_RCR_UFLEN | YU_RCR_MUFLEN); 1023 1.84 christos break; 1024 1.84 christos default: 1025 1.84 christos aprint_error_dev(sc_if->sk_dev, "Can't set promisc for %d\n", 1026 1.84 christos sc->sk_type); 1027 1.84 christos break; 1028 1.84 christos } 1029 1.84 christos } 1030 1.84 christos 1031 1.102 maxv static int 1032 1.37 christos sk_ioctl(struct ifnet *ifp, u_long command, void *data) 1033 1.1 jdolecek { 1034 1.1 jdolecek struct sk_if_softc *sc_if = ifp->if_softc; 1035 1.1 jdolecek int s, error = 0; 1036 1.1 jdolecek 1037 1.1 jdolecek /* DPRINTFN(2, ("sk_ioctl\n")); */ 1038 1.1 jdolecek 1039 1.1 jdolecek s = splnet(); 1040 1.1 jdolecek 1041 1.31 riz switch (command) { 1042 1.1 jdolecek 1043 1.1 jdolecek case SIOCSIFFLAGS: 1044 1.92 msaitoh DPRINTFN(2, ("sk_ioctl IFFLAGS\n")); 1045 1.55 dyoung if ((error = ifioctl_common(ifp, command, data)) != 0) 1046 1.55 dyoung break; 1047 1.84 christos switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { 1048 1.84 christos case IFF_RUNNING: 1049 1.84 christos sk_stop(ifp, 1); 1050 1.84 christos break; 1051 1.84 christos case IFF_UP: 1052 1.84 christos sk_init(ifp); 1053 1.84 christos break; 1054 1.84 christos case IFF_UP | IFF_RUNNING: 1055 1.84 christos if ((ifp->if_flags ^ sc_if->sk_if_flags) == IFF_PROMISC) { 1056 1.84 christos sk_promisc(sc_if, ifp->if_flags & IFF_PROMISC); 1057 1.1 jdolecek sk_setmulti(sc_if); 1058 1.1 jdolecek } else 1059 1.84 christos sk_init(ifp); 1060 1.84 christos break; 1061 1.1 jdolecek } 1062 1.1 jdolecek sc_if->sk_if_flags = ifp->if_flags; 1063 1.1 jdolecek error = 0; 1064 1.1 jdolecek break; 1065 1.1 jdolecek 1066 1.1 jdolecek default: 1067 1.92 msaitoh DPRINTFN(2, ("sk_ioctl ETHER\n")); 1068 1.47 dyoung if ((error = ether_ioctl(ifp, command, data)) != ENETRESET) 1069 1.47 dyoung break; 1070 1.47 dyoung 1071 1.47 dyoung error = 0; 1072 1.1 jdolecek 1073 1.47 dyoung if (command != SIOCADDMULTI && command != SIOCDELMULTI) 1074 1.47 dyoung ; 1075 1.47 dyoung else if (ifp->if_flags & IFF_RUNNING) { 1076 1.47 dyoung sk_setmulti(sc_if); 1077 1.47 dyoung DPRINTFN(2, ("sk_ioctl setmulti called\n")); 1078 1.1 jdolecek } 1079 1.1 jdolecek break; 1080 1.1 jdolecek } 1081 1.1 jdolecek 1082 1.1 jdolecek splx(s); 1083 1.31 riz return error; 1084 1.1 jdolecek } 1085 1.1 jdolecek 1086 1.102 maxv static void 1087 1.20 riz sk_update_int_mod(struct sk_softc *sc) 1088 1.20 riz { 1089 1.91 msaitoh uint32_t imtimer_ticks; 1090 1.20 riz 1091 1.20 riz /* 1092 1.92 msaitoh * Configure interrupt moderation. The moderation timer 1093 1.20 riz * defers interrupts specified in the interrupt moderation 1094 1.20 riz * timer mask based on the timeout specified in the interrupt 1095 1.20 riz * moderation timer init register. Each bit in the timer 1096 1.20 riz * register represents one tick, so to specify a timeout in 1097 1.20 riz * microseconds, we have to multiply by the correct number of 1098 1.20 riz * ticks-per-microsecond. 1099 1.20 riz */ 1100 1.20 riz switch (sc->sk_type) { 1101 1.20 riz case SK_GENESIS: 1102 1.36 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_GENESIS; 1103 1.20 riz break; 1104 1.20 riz case SK_YUKON_EC: 1105 1.36 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON_EC; 1106 1.20 riz break; 1107 1.20 riz default: 1108 1.36 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON; 1109 1.20 riz } 1110 1.51 christos aprint_verbose_dev(sc->sk_dev, "interrupt moderation is %d us\n", 1111 1.48 cegger sc->sk_int_mod); 1112 1.92 msaitoh sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(sc->sk_int_mod)); 1113 1.96 msaitoh sk_win_write_4(sc, SK_IMMR, SK_ISR_TX1_S_EOF | SK_ISR_TX2_S_EOF | 1114 1.96 msaitoh SK_ISR_RX1_EOF | SK_ISR_RX2_EOF); 1115 1.92 msaitoh sk_win_write_1(sc, SK_IMTIMERCTL, SK_IMCTL_START); 1116 1.20 riz sc->sk_int_mod_pending = 0; 1117 1.20 riz } 1118 1.20 riz 1119 1.1 jdolecek /* 1120 1.1 jdolecek * Lookup: Check the PCI vendor and device, and return a pointer to 1121 1.1 jdolecek * The structure if the IDs match against our list. 1122 1.1 jdolecek */ 1123 1.1 jdolecek 1124 1.1 jdolecek /* 1125 1.1 jdolecek * Probe for a SysKonnect GEnesis chip. 1126 1.1 jdolecek */ 1127 1.1 jdolecek 1128 1.102 maxv static int 1129 1.51 christos skc_probe(device_t parent, cfdata_t match, void *aux) 1130 1.1 jdolecek { 1131 1.1 jdolecek struct pci_attach_args *pa = (struct pci_attach_args *)aux; 1132 1.18 riz pcireg_t subid; 1133 1.18 riz 1134 1.18 riz subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 1135 1.18 riz 1136 1.18 riz /* special-case Linksys EG1032, since rev 3 uses re(4) */ 1137 1.18 riz if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_LINKSYS && 1138 1.18 riz PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LINKSYS_EG1032 && 1139 1.18 riz subid == SK_LINKSYS_EG1032_SUBID) 1140 1.31 riz return 1; 1141 1.14 perry 1142 1.108 thorpej return pci_compatible_match(pa, compat_data); 1143 1.1 jdolecek } 1144 1.1 jdolecek 1145 1.1 jdolecek /* 1146 1.1 jdolecek * Force the GEnesis into reset, then bring it out of reset. 1147 1.1 jdolecek */ 1148 1.102 maxv static void 1149 1.100 msaitoh sk_reset(struct sk_softc *sc) 1150 1.1 jdolecek { 1151 1.1 jdolecek DPRINTFN(2, ("sk_reset\n")); 1152 1.1 jdolecek 1153 1.1 jdolecek CSR_WRITE_2(sc, SK_CSR, SK_CSR_SW_RESET); 1154 1.1 jdolecek CSR_WRITE_2(sc, SK_CSR, SK_CSR_MASTER_RESET); 1155 1.11 skd if (SK_YUKON_FAMILY(sc->sk_type)) 1156 1.1 jdolecek CSR_WRITE_2(sc, SK_LINK_CTRL, SK_LINK_RESET_SET); 1157 1.1 jdolecek 1158 1.1 jdolecek DELAY(1000); 1159 1.1 jdolecek CSR_WRITE_2(sc, SK_CSR, SK_CSR_SW_UNRESET); 1160 1.1 jdolecek DELAY(2); 1161 1.1 jdolecek CSR_WRITE_2(sc, SK_CSR, SK_CSR_MASTER_UNRESET); 1162 1.11 skd if (SK_YUKON_FAMILY(sc->sk_type)) 1163 1.1 jdolecek CSR_WRITE_2(sc, SK_LINK_CTRL, SK_LINK_RESET_CLEAR); 1164 1.1 jdolecek 1165 1.1 jdolecek DPRINTFN(2, ("sk_reset: sk_csr=%x\n", CSR_READ_2(sc, SK_CSR))); 1166 1.1 jdolecek DPRINTFN(2, ("sk_reset: sk_link_ctrl=%x\n", 1167 1.1 jdolecek CSR_READ_2(sc, SK_LINK_CTRL))); 1168 1.1 jdolecek 1169 1.1 jdolecek if (sc->sk_type == SK_GENESIS) { 1170 1.1 jdolecek /* Configure packet arbiter */ 1171 1.1 jdolecek sk_win_write_2(sc, SK_PKTARB_CTL, SK_PKTARBCTL_UNRESET); 1172 1.1 jdolecek sk_win_write_2(sc, SK_RXPA1_TINIT, SK_PKTARB_TIMEOUT); 1173 1.1 jdolecek sk_win_write_2(sc, SK_TXPA1_TINIT, SK_PKTARB_TIMEOUT); 1174 1.1 jdolecek sk_win_write_2(sc, SK_RXPA2_TINIT, SK_PKTARB_TIMEOUT); 1175 1.1 jdolecek sk_win_write_2(sc, SK_TXPA2_TINIT, SK_PKTARB_TIMEOUT); 1176 1.1 jdolecek } 1177 1.1 jdolecek 1178 1.1 jdolecek /* Enable RAM interface */ 1179 1.1 jdolecek sk_win_write_4(sc, SK_RAMCTL, SK_RAMCTL_UNRESET); 1180 1.1 jdolecek 1181 1.20 riz sk_update_int_mod(sc); 1182 1.1 jdolecek } 1183 1.1 jdolecek 1184 1.102 maxv static int 1185 1.51 christos sk_probe(device_t parent, cfdata_t match, void *aux) 1186 1.1 jdolecek { 1187 1.1 jdolecek struct skc_attach_args *sa = aux; 1188 1.1 jdolecek 1189 1.1 jdolecek if (sa->skc_port != SK_PORT_A && sa->skc_port != SK_PORT_B) 1190 1.31 riz return 0; 1191 1.1 jdolecek 1192 1.31 riz return 1; 1193 1.1 jdolecek } 1194 1.1 jdolecek 1195 1.1 jdolecek /* 1196 1.1 jdolecek * Each XMAC chip is attached as a separate logical IP interface. 1197 1.1 jdolecek * Single port cards will have only one logical interface of course. 1198 1.1 jdolecek */ 1199 1.102 maxv static void 1200 1.51 christos sk_attach(device_t parent, device_t self, void *aux) 1201 1.1 jdolecek { 1202 1.51 christos struct sk_if_softc *sc_if = device_private(self); 1203 1.98 msaitoh struct mii_data *mii = &sc_if->sk_mii; 1204 1.51 christos struct sk_softc *sc = device_private(parent); 1205 1.1 jdolecek struct skc_attach_args *sa = aux; 1206 1.3 briggs struct sk_txmap_entry *entry; 1207 1.1 jdolecek struct ifnet *ifp; 1208 1.3 briggs bus_dma_segment_t seg; 1209 1.3 briggs bus_dmamap_t dmamap; 1210 1.67 phx prop_data_t data; 1211 1.37 christos void *kva; 1212 1.1 jdolecek int i, rseg; 1213 1.56 cegger int mii_flags = 0; 1214 1.1 jdolecek 1215 1.44 jmcneill aprint_naive("\n"); 1216 1.44 jmcneill 1217 1.51 christos sc_if->sk_dev = self; 1218 1.1 jdolecek sc_if->sk_port = sa->skc_port; 1219 1.1 jdolecek sc_if->sk_softc = sc; 1220 1.1 jdolecek sc->sk_if[sa->skc_port] = sc_if; 1221 1.1 jdolecek 1222 1.1 jdolecek if (sa->skc_port == SK_PORT_A) 1223 1.1 jdolecek sc_if->sk_tx_bmu = SK_BMU_TXS_CSR0; 1224 1.1 jdolecek if (sa->skc_port == SK_PORT_B) 1225 1.1 jdolecek sc_if->sk_tx_bmu = SK_BMU_TXS_CSR1; 1226 1.1 jdolecek 1227 1.1 jdolecek DPRINTFN(2, ("begin sk_attach: port=%d\n", sc_if->sk_port)); 1228 1.1 jdolecek 1229 1.1 jdolecek /* 1230 1.1 jdolecek * Get station address for this interface. Note that 1231 1.1 jdolecek * dual port cards actually come with three station 1232 1.1 jdolecek * addresses: one for each port, plus an extra. The 1233 1.1 jdolecek * extra one is used by the SysKonnect driver software 1234 1.1 jdolecek * as a 'virtual' station address for when both ports 1235 1.1 jdolecek * are operating in failover mode. Currently we don't 1236 1.1 jdolecek * use this extra address. 1237 1.1 jdolecek */ 1238 1.67 phx data = prop_dictionary_get(device_properties(self), "mac-address"); 1239 1.67 phx if (data != NULL) { 1240 1.67 phx /* 1241 1.67 phx * Try to get the station address from device properties 1242 1.67 phx * first, in case the ROM is missing. 1243 1.67 phx */ 1244 1.67 phx KASSERT(prop_object_type(data) == PROP_TYPE_DATA); 1245 1.67 phx KASSERT(prop_data_size(data) == ETHER_ADDR_LEN); 1246 1.106 msaitoh memcpy(sc_if->sk_enaddr, prop_data_value(data), 1247 1.67 phx ETHER_ADDR_LEN); 1248 1.67 phx } else 1249 1.67 phx for (i = 0; i < ETHER_ADDR_LEN; i++) 1250 1.67 phx sc_if->sk_enaddr[i] = sk_win_read_1(sc, 1251 1.67 phx SK_MAC0_0 + (sa->skc_port * 8) + i); 1252 1.1 jdolecek 1253 1.3 briggs aprint_normal(": Ethernet address %s\n", 1254 1.1 jdolecek ether_sprintf(sc_if->sk_enaddr)); 1255 1.1 jdolecek 1256 1.1 jdolecek /* 1257 1.1 jdolecek * Set up RAM buffer addresses. The NIC will have a certain 1258 1.1 jdolecek * amount of SRAM on it, somewhere between 512K and 2MB. We 1259 1.1 jdolecek * need to divide this up a) between the transmitter and 1260 1.92 msaitoh * receiver and b) between the two XMACs, if this is a 1261 1.22 riz * dual port NIC. Our algorithm is to divide up the memory 1262 1.1 jdolecek * evenly so that everyone gets a fair share. 1263 1.1 jdolecek */ 1264 1.1 jdolecek if (sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC) { 1265 1.91 msaitoh uint32_t chunk, val; 1266 1.1 jdolecek 1267 1.1 jdolecek chunk = sc->sk_ramsize / 2; 1268 1.91 msaitoh val = sc->sk_rboff / sizeof(uint64_t); 1269 1.1 jdolecek sc_if->sk_rx_ramstart = val; 1270 1.91 msaitoh val += (chunk / sizeof(uint64_t)); 1271 1.1 jdolecek sc_if->sk_rx_ramend = val - 1; 1272 1.1 jdolecek sc_if->sk_tx_ramstart = val; 1273 1.91 msaitoh val += (chunk / sizeof(uint64_t)); 1274 1.1 jdolecek sc_if->sk_tx_ramend = val - 1; 1275 1.1 jdolecek } else { 1276 1.91 msaitoh uint32_t chunk, val; 1277 1.1 jdolecek 1278 1.1 jdolecek chunk = sc->sk_ramsize / 4; 1279 1.1 jdolecek val = (sc->sk_rboff + (chunk * 2 * sc_if->sk_port)) / 1280 1.91 msaitoh sizeof(uint64_t); 1281 1.1 jdolecek sc_if->sk_rx_ramstart = val; 1282 1.91 msaitoh val += (chunk / sizeof(uint64_t)); 1283 1.1 jdolecek sc_if->sk_rx_ramend = val - 1; 1284 1.1 jdolecek sc_if->sk_tx_ramstart = val; 1285 1.91 msaitoh val += (chunk / sizeof(uint64_t)); 1286 1.1 jdolecek sc_if->sk_tx_ramend = val - 1; 1287 1.1 jdolecek } 1288 1.1 jdolecek 1289 1.1 jdolecek DPRINTFN(2, ("sk_attach: rx_ramstart=%#x rx_ramend=%#x\n" 1290 1.92 msaitoh " tx_ramstart=%#x tx_ramend=%#x\n", 1291 1.1 jdolecek sc_if->sk_rx_ramstart, sc_if->sk_rx_ramend, 1292 1.1 jdolecek sc_if->sk_tx_ramstart, sc_if->sk_tx_ramend)); 1293 1.1 jdolecek 1294 1.1 jdolecek /* Read and save PHY type and set PHY address */ 1295 1.1 jdolecek sc_if->sk_phytype = sk_win_read_1(sc, SK_EPROM1) & 0xF; 1296 1.1 jdolecek switch (sc_if->sk_phytype) { 1297 1.1 jdolecek case SK_PHYTYPE_XMAC: 1298 1.1 jdolecek sc_if->sk_phyaddr = SK_PHYADDR_XMAC; 1299 1.1 jdolecek break; 1300 1.1 jdolecek case SK_PHYTYPE_BCOM: 1301 1.1 jdolecek sc_if->sk_phyaddr = SK_PHYADDR_BCOM; 1302 1.1 jdolecek break; 1303 1.1 jdolecek case SK_PHYTYPE_MARV_COPPER: 1304 1.1 jdolecek sc_if->sk_phyaddr = SK_PHYADDR_MARV; 1305 1.1 jdolecek break; 1306 1.1 jdolecek default: 1307 1.51 christos aprint_error_dev(sc->sk_dev, "unsupported PHY type: %d\n", 1308 1.48 cegger sc_if->sk_phytype); 1309 1.1 jdolecek return; 1310 1.1 jdolecek } 1311 1.1 jdolecek 1312 1.1 jdolecek /* Allocate the descriptor queues. */ 1313 1.1 jdolecek if (bus_dmamem_alloc(sc->sc_dmatag, sizeof(struct sk_ring_data), 1314 1.1 jdolecek PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) { 1315 1.51 christos aprint_error_dev(sc->sk_dev, "can't alloc rx buffers\n"); 1316 1.1 jdolecek goto fail; 1317 1.1 jdolecek } 1318 1.1 jdolecek if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, 1319 1.1 jdolecek sizeof(struct sk_ring_data), &kva, BUS_DMA_NOWAIT)) { 1320 1.51 christos aprint_error_dev(sc_if->sk_dev, 1321 1.51 christos "can't map dma buffers (%lu bytes)\n", 1322 1.51 christos (u_long) sizeof(struct sk_ring_data)); 1323 1.1 jdolecek bus_dmamem_free(sc->sc_dmatag, &seg, rseg); 1324 1.1 jdolecek goto fail; 1325 1.1 jdolecek } 1326 1.1 jdolecek if (bus_dmamap_create(sc->sc_dmatag, sizeof(struct sk_ring_data), 1, 1327 1.1 jdolecek sizeof(struct sk_ring_data), 0, BUS_DMA_NOWAIT, 1328 1.92 msaitoh &sc_if->sk_ring_map)) { 1329 1.51 christos aprint_error_dev(sc_if->sk_dev, "can't create dma map\n"); 1330 1.1 jdolecek bus_dmamem_unmap(sc->sc_dmatag, kva, 1331 1.1 jdolecek sizeof(struct sk_ring_data)); 1332 1.1 jdolecek bus_dmamem_free(sc->sc_dmatag, &seg, rseg); 1333 1.1 jdolecek goto fail; 1334 1.1 jdolecek } 1335 1.1 jdolecek if (bus_dmamap_load(sc->sc_dmatag, sc_if->sk_ring_map, kva, 1336 1.1 jdolecek sizeof(struct sk_ring_data), NULL, BUS_DMA_NOWAIT)) { 1337 1.51 christos aprint_error_dev(sc_if->sk_dev, "can't load dma map\n"); 1338 1.1 jdolecek bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map); 1339 1.1 jdolecek bus_dmamem_unmap(sc->sc_dmatag, kva, 1340 1.1 jdolecek sizeof(struct sk_ring_data)); 1341 1.1 jdolecek bus_dmamem_free(sc->sc_dmatag, &seg, rseg); 1342 1.1 jdolecek goto fail; 1343 1.1 jdolecek } 1344 1.3 briggs 1345 1.3 briggs for (i = 0; i < SK_RX_RING_CNT; i++) 1346 1.3 briggs sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf = NULL; 1347 1.3 briggs 1348 1.11 skd SIMPLEQ_INIT(&sc_if->sk_txmap_head); 1349 1.3 briggs for (i = 0; i < SK_TX_RING_CNT; i++) { 1350 1.3 briggs sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf = NULL; 1351 1.3 briggs 1352 1.22 riz if (bus_dmamap_create(sc->sc_dmatag, SK_JLEN, SK_NTXSEG, 1353 1.22 riz SK_JLEN, 0, BUS_DMA_NOWAIT, &dmamap)) { 1354 1.51 christos aprint_error_dev(sc_if->sk_dev, 1355 1.51 christos "Can't create TX dmamap\n"); 1356 1.3 briggs bus_dmamap_unload(sc->sc_dmatag, sc_if->sk_ring_map); 1357 1.3 briggs bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map); 1358 1.3 briggs bus_dmamem_unmap(sc->sc_dmatag, kva, 1359 1.3 briggs sizeof(struct sk_ring_data)); 1360 1.3 briggs bus_dmamem_free(sc->sc_dmatag, &seg, rseg); 1361 1.3 briggs goto fail; 1362 1.3 briggs } 1363 1.3 briggs 1364 1.101 chs entry = malloc(sizeof(*entry), M_DEVBUF, M_WAITOK); 1365 1.3 briggs entry->dmamap = dmamap; 1366 1.11 skd SIMPLEQ_INSERT_HEAD(&sc_if->sk_txmap_head, entry, link); 1367 1.3 briggs } 1368 1.3 briggs 1369 1.92 msaitoh sc_if->sk_rdata = (struct sk_ring_data *)kva; 1370 1.59 cegger memset(sc_if->sk_rdata, 0, sizeof(struct sk_ring_data)); 1371 1.1 jdolecek 1372 1.22 riz ifp = &sc_if->sk_ethercom.ec_if; 1373 1.22 riz /* Try to allocate memory for jumbo buffers. */ 1374 1.22 riz if (sk_alloc_jumbo_mem(sc_if)) { 1375 1.100 msaitoh aprint_error("%s: jumbo buffer allocation failed\n", 1376 1.100 msaitoh ifp->if_xname); 1377 1.22 riz goto fail; 1378 1.22 riz } 1379 1.73 christos sc_if->sk_ethercom.ec_capabilities = ETHERCAP_VLAN_MTU 1380 1.22 riz | ETHERCAP_JUMBO_MTU; 1381 1.6 tls 1382 1.1 jdolecek ifp->if_softc = sc_if; 1383 1.1 jdolecek ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 1384 1.1 jdolecek ifp->if_ioctl = sk_ioctl; 1385 1.1 jdolecek ifp->if_start = sk_start; 1386 1.1 jdolecek ifp->if_stop = sk_stop; 1387 1.1 jdolecek ifp->if_init = sk_init; 1388 1.1 jdolecek ifp->if_watchdog = sk_watchdog; 1389 1.6 tls ifp->if_capabilities = 0; 1390 1.1 jdolecek IFQ_SET_MAXLEN(&ifp->if_snd, SK_TX_RING_CNT - 1); 1391 1.1 jdolecek IFQ_SET_READY(&ifp->if_snd); 1392 1.51 christos strlcpy(ifp->if_xname, device_xname(sc_if->sk_dev), IFNAMSIZ); 1393 1.1 jdolecek 1394 1.1 jdolecek /* 1395 1.1 jdolecek * Do miibus setup. 1396 1.1 jdolecek */ 1397 1.1 jdolecek switch (sc->sk_type) { 1398 1.1 jdolecek case SK_GENESIS: 1399 1.99 msaitoh sk_unreset_xmac(sc_if); 1400 1.1 jdolecek break; 1401 1.1 jdolecek case SK_YUKON: 1402 1.11 skd case SK_YUKON_LITE: 1403 1.11 skd case SK_YUKON_LP: 1404 1.99 msaitoh sk_unreset_yukon(sc_if); 1405 1.1 jdolecek break; 1406 1.1 jdolecek default: 1407 1.51 christos aprint_error_dev(sc->sk_dev, "unknown device type %d\n", 1408 1.48 cegger sc->sk_type); 1409 1.40 briggs goto fail; 1410 1.1 jdolecek } 1411 1.1 jdolecek 1412 1.92 msaitoh DPRINTFN(2, ("sk_attach: 1\n")); 1413 1.1 jdolecek 1414 1.98 msaitoh mii->mii_ifp = ifp; 1415 1.1 jdolecek switch (sc->sk_type) { 1416 1.1 jdolecek case SK_GENESIS: 1417 1.98 msaitoh mii->mii_readreg = sk_xmac_miibus_readreg; 1418 1.98 msaitoh mii->mii_writereg = sk_xmac_miibus_writereg; 1419 1.98 msaitoh mii->mii_statchg = sk_xmac_miibus_statchg; 1420 1.1 jdolecek break; 1421 1.1 jdolecek case SK_YUKON: 1422 1.11 skd case SK_YUKON_LITE: 1423 1.11 skd case SK_YUKON_LP: 1424 1.98 msaitoh mii->mii_readreg = sk_marv_miibus_readreg; 1425 1.98 msaitoh mii->mii_writereg = sk_marv_miibus_writereg; 1426 1.98 msaitoh mii->mii_statchg = sk_marv_miibus_statchg; 1427 1.56 cegger mii_flags = MIIF_DOPAUSE; 1428 1.1 jdolecek break; 1429 1.1 jdolecek } 1430 1.1 jdolecek 1431 1.98 msaitoh sc_if->sk_ethercom.ec_mii = mii; 1432 1.98 msaitoh ifmedia_init(&mii->mii_media, 0, sk_ifmedia_upd, ether_mediastatus); 1433 1.98 msaitoh mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, 1434 1.56 cegger MII_OFFSET_ANY, mii_flags); 1435 1.98 msaitoh if (LIST_EMPTY(&mii->mii_phys)) { 1436 1.51 christos aprint_error_dev(sc_if->sk_dev, "no PHY found!\n"); 1437 1.98 msaitoh ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_MANUAL, 0, NULL); 1438 1.98 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_MANUAL); 1439 1.31 riz } else 1440 1.98 msaitoh ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 1441 1.1 jdolecek 1442 1.41 ad callout_init(&sc_if->sk_tick_ch, 0); 1443 1.96 msaitoh callout_reset(&sc_if->sk_tick_ch, hz, sk_tick, sc_if); 1444 1.1 jdolecek 1445 1.1 jdolecek DPRINTFN(2, ("sk_attach: 1\n")); 1446 1.1 jdolecek 1447 1.1 jdolecek /* 1448 1.1 jdolecek * Call MI attach routines. 1449 1.1 jdolecek */ 1450 1.1 jdolecek if_attach(ifp); 1451 1.83 ozaki if_deferred_start_init(ifp, NULL); 1452 1.1 jdolecek 1453 1.1 jdolecek ether_ifattach(ifp, sc_if->sk_enaddr); 1454 1.1 jdolecek 1455 1.88 jdolecek if (sc->rnd_attached++ == 0) { 1456 1.92 msaitoh rnd_attach_source(&sc->rnd_source, device_xname(sc->sk_dev), 1457 1.88 jdolecek RND_TYPE_NET, RND_FLAG_DEFAULT); 1458 1.88 jdolecek } 1459 1.1 jdolecek 1460 1.61 tsutsui if (pmf_device_register(self, NULL, sk_resume)) 1461 1.61 tsutsui pmf_class_network_register(self, ifp); 1462 1.61 tsutsui else 1463 1.60 kefren aprint_error_dev(self, "couldn't establish power handler\n"); 1464 1.60 kefren 1465 1.1 jdolecek DPRINTFN(2, ("sk_attach: end\n")); 1466 1.1 jdolecek 1467 1.1 jdolecek return; 1468 1.1 jdolecek 1469 1.1 jdolecek fail: 1470 1.1 jdolecek sc->sk_if[sa->skc_port] = NULL; 1471 1.1 jdolecek } 1472 1.1 jdolecek 1473 1.102 maxv static int 1474 1.1 jdolecek skcprint(void *aux, const char *pnp) 1475 1.1 jdolecek { 1476 1.1 jdolecek struct skc_attach_args *sa = aux; 1477 1.1 jdolecek 1478 1.1 jdolecek if (pnp) 1479 1.3 briggs aprint_normal("sk port %c at %s", 1480 1.1 jdolecek (sa->skc_port == SK_PORT_A) ? 'A' : 'B', pnp); 1481 1.1 jdolecek else 1482 1.3 briggs aprint_normal(" port %c", 1483 1.3 briggs (sa->skc_port == SK_PORT_A) ? 'A' : 'B'); 1484 1.31 riz return UNCONF; 1485 1.1 jdolecek } 1486 1.1 jdolecek 1487 1.1 jdolecek /* 1488 1.1 jdolecek * Attach the interface. Allocate softc structures, do ifmedia 1489 1.1 jdolecek * setup and ethernet/BPF attach. 1490 1.1 jdolecek */ 1491 1.102 maxv static void 1492 1.51 christos skc_attach(device_t parent, device_t self, void *aux) 1493 1.1 jdolecek { 1494 1.51 christos struct sk_softc *sc = device_private(self); 1495 1.1 jdolecek struct pci_attach_args *pa = aux; 1496 1.1 jdolecek struct skc_attach_args skca; 1497 1.1 jdolecek pci_chipset_tag_t pc = pa->pa_pc; 1498 1.27 riz #ifndef SK_USEIOSPACE 1499 1.1 jdolecek pcireg_t memtype; 1500 1.27 riz #endif 1501 1.1 jdolecek pci_intr_handle_t ih; 1502 1.1 jdolecek const char *intrstr = NULL; 1503 1.1 jdolecek bus_addr_t iobase; 1504 1.1 jdolecek bus_size_t iosize; 1505 1.28 riz int rc, sk_nodenum; 1506 1.91 msaitoh uint32_t command; 1507 1.15 christos const char *revstr; 1508 1.20 riz const struct sysctlnode *node; 1509 1.77 christos char intrbuf[PCI_INTRSTR_LEN]; 1510 1.1 jdolecek 1511 1.51 christos sc->sk_dev = self; 1512 1.44 jmcneill aprint_naive("\n"); 1513 1.44 jmcneill 1514 1.1 jdolecek DPRINTFN(2, ("begin skc_attach\n")); 1515 1.1 jdolecek 1516 1.1 jdolecek /* 1517 1.1 jdolecek * Handle power management nonsense. 1518 1.1 jdolecek */ 1519 1.1 jdolecek command = pci_conf_read(pc, pa->pa_tag, SK_PCI_CAPID) & 0x000000FF; 1520 1.1 jdolecek 1521 1.1 jdolecek if (command == 0x01) { 1522 1.1 jdolecek command = pci_conf_read(pc, pa->pa_tag, SK_PCI_PWRMGMTCTRL); 1523 1.1 jdolecek if (command & SK_PSTATE_MASK) { 1524 1.91 msaitoh uint32_t xiobase, membase, irq; 1525 1.1 jdolecek 1526 1.1 jdolecek /* Save important PCI config data. */ 1527 1.15 christos xiobase = pci_conf_read(pc, pa->pa_tag, SK_PCI_LOIO); 1528 1.1 jdolecek membase = pci_conf_read(pc, pa->pa_tag, SK_PCI_LOMEM); 1529 1.1 jdolecek irq = pci_conf_read(pc, pa->pa_tag, SK_PCI_INTLINE); 1530 1.1 jdolecek 1531 1.1 jdolecek /* Reset the power state. */ 1532 1.51 christos aprint_normal_dev(sc->sk_dev, 1533 1.51 christos "chip is in D%d power mode -- setting to D0\n", 1534 1.1 jdolecek command & SK_PSTATE_MASK); 1535 1.1 jdolecek command &= 0xFFFFFFFC; 1536 1.1 jdolecek pci_conf_write(pc, pa->pa_tag, 1537 1.1 jdolecek SK_PCI_PWRMGMTCTRL, command); 1538 1.1 jdolecek 1539 1.1 jdolecek /* Restore PCI config data. */ 1540 1.15 christos pci_conf_write(pc, pa->pa_tag, SK_PCI_LOIO, xiobase); 1541 1.1 jdolecek pci_conf_write(pc, pa->pa_tag, SK_PCI_LOMEM, membase); 1542 1.1 jdolecek pci_conf_write(pc, pa->pa_tag, SK_PCI_INTLINE, irq); 1543 1.1 jdolecek } 1544 1.1 jdolecek } 1545 1.1 jdolecek 1546 1.1 jdolecek /* 1547 1.69 phx * The firmware might have configured the interface to revert the 1548 1.69 phx * byte order in all descriptors. Make that undone. 1549 1.69 phx */ 1550 1.69 phx command = pci_conf_read(pc, pa->pa_tag, SK_PCI_OURREG2); 1551 1.69 phx if (command & SK_REG2_REV_DESC) 1552 1.69 phx pci_conf_write(pc, pa->pa_tag, SK_PCI_OURREG2, 1553 1.69 phx command & ~SK_REG2_REV_DESC); 1554 1.69 phx 1555 1.69 phx /* 1556 1.1 jdolecek * Map control/status registers. 1557 1.1 jdolecek */ 1558 1.1 jdolecek command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 1559 1.1 jdolecek command |= PCI_COMMAND_IO_ENABLE | 1560 1.1 jdolecek PCI_COMMAND_MEM_ENABLE | 1561 1.1 jdolecek PCI_COMMAND_MASTER_ENABLE; 1562 1.1 jdolecek pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); 1563 1.1 jdolecek command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 1564 1.1 jdolecek 1565 1.1 jdolecek #ifdef SK_USEIOSPACE 1566 1.1 jdolecek if (!(command & PCI_COMMAND_IO_ENABLE)) { 1567 1.3 briggs aprint_error(": failed to enable I/O ports!\n"); 1568 1.28 riz return; 1569 1.1 jdolecek } 1570 1.1 jdolecek /* 1571 1.1 jdolecek * Map control/status registers. 1572 1.1 jdolecek */ 1573 1.1 jdolecek if (pci_mapreg_map(pa, SK_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0, 1574 1.27 riz &sc->sk_btag, &sc->sk_bhandle, 1575 1.27 riz &iobase, &iosize)) { 1576 1.3 briggs aprint_error(": can't find i/o space\n"); 1577 1.28 riz return; 1578 1.1 jdolecek } 1579 1.1 jdolecek #else 1580 1.1 jdolecek if (!(command & PCI_COMMAND_MEM_ENABLE)) { 1581 1.3 briggs aprint_error(": failed to enable memory mapping!\n"); 1582 1.28 riz return; 1583 1.1 jdolecek } 1584 1.1 jdolecek memtype = pci_mapreg_type(pc, pa->pa_tag, SK_PCI_LOMEM); 1585 1.1 jdolecek switch (memtype) { 1586 1.92 msaitoh case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: 1587 1.92 msaitoh case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: 1588 1.92 msaitoh if (pci_mapreg_map(pa, SK_PCI_LOMEM, 1589 1.1 jdolecek memtype, 0, &sc->sk_btag, &sc->sk_bhandle, 1590 1.1 jdolecek &iobase, &iosize) == 0) 1591 1.92 msaitoh break; 1592 1.94 mrg /* FALLTHROUGH */ 1593 1.92 msaitoh default: 1594 1.92 msaitoh aprint_error_dev(sc->sk_dev, "can't find mem space\n"); 1595 1.92 msaitoh return; 1596 1.1 jdolecek } 1597 1.1 jdolecek 1598 1.68 jym DPRINTFN(2, ("skc_attach: iobase=%#" PRIxPADDR ", iosize=%zx\n", 1599 1.68 jym iobase, iosize)); 1600 1.1 jdolecek #endif 1601 1.1 jdolecek sc->sc_dmatag = pa->pa_dmat; 1602 1.1 jdolecek 1603 1.11 skd sc->sk_type = sk_win_read_1(sc, SK_CHIPVER); 1604 1.31 riz sc->sk_rev = (sk_win_read_1(sc, SK_CONFIG) >> 4); 1605 1.11 skd 1606 1.11 skd /* bail out here if chip is not recognized */ 1607 1.11 skd if ( sc->sk_type != SK_GENESIS && ! SK_YUKON_FAMILY(sc->sk_type)) { 1608 1.51 christos aprint_error_dev(sc->sk_dev, "unknown chip type\n"); 1609 1.11 skd goto fail; 1610 1.11 skd } 1611 1.40 briggs if (SK_IS_YUKON2(sc)) { 1612 1.51 christos aprint_error_dev(sc->sk_dev, 1613 1.51 christos "Does not support Yukon2--try msk(4).\n"); 1614 1.40 briggs goto fail; 1615 1.40 briggs } 1616 1.1 jdolecek DPRINTFN(2, ("skc_attach: allocate interrupt\n")); 1617 1.1 jdolecek 1618 1.1 jdolecek /* Allocate interrupt */ 1619 1.1 jdolecek if (pci_intr_map(pa, &ih)) { 1620 1.3 briggs aprint_error(": couldn't map interrupt\n"); 1621 1.1 jdolecek goto fail; 1622 1.1 jdolecek } 1623 1.1 jdolecek 1624 1.77 christos intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); 1625 1.100 msaitoh sc->sk_intrhand = pci_intr_establish_xname(pc, ih, IPL_NET, sk_intr, 1626 1.100 msaitoh sc, device_xname(sc->sk_dev)); 1627 1.1 jdolecek if (sc->sk_intrhand == NULL) { 1628 1.3 briggs aprint_error(": couldn't establish interrupt"); 1629 1.1 jdolecek if (intrstr != NULL) 1630 1.62 njoly aprint_error(" at %s", intrstr); 1631 1.62 njoly aprint_error("\n"); 1632 1.1 jdolecek goto fail; 1633 1.1 jdolecek } 1634 1.3 briggs aprint_normal(": %s\n", intrstr); 1635 1.1 jdolecek 1636 1.1 jdolecek /* Reset the adapter. */ 1637 1.1 jdolecek sk_reset(sc); 1638 1.1 jdolecek 1639 1.1 jdolecek /* Read and save vital product data from EEPROM. */ 1640 1.1 jdolecek sk_vpd_read(sc); 1641 1.1 jdolecek 1642 1.1 jdolecek if (sc->sk_type == SK_GENESIS) { 1643 1.91 msaitoh uint8_t val = sk_win_read_1(sc, SK_EPROM0); 1644 1.1 jdolecek /* Read and save RAM size and RAMbuffer offset */ 1645 1.31 riz switch (val) { 1646 1.1 jdolecek case SK_RAMSIZE_512K_64: 1647 1.1 jdolecek sc->sk_ramsize = 0x80000; 1648 1.1 jdolecek sc->sk_rboff = SK_RBOFF_0; 1649 1.1 jdolecek break; 1650 1.1 jdolecek case SK_RAMSIZE_1024K_64: 1651 1.1 jdolecek sc->sk_ramsize = 0x100000; 1652 1.1 jdolecek sc->sk_rboff = SK_RBOFF_80000; 1653 1.1 jdolecek break; 1654 1.1 jdolecek case SK_RAMSIZE_1024K_128: 1655 1.1 jdolecek sc->sk_ramsize = 0x100000; 1656 1.1 jdolecek sc->sk_rboff = SK_RBOFF_0; 1657 1.1 jdolecek break; 1658 1.1 jdolecek case SK_RAMSIZE_2048K_128: 1659 1.1 jdolecek sc->sk_ramsize = 0x200000; 1660 1.1 jdolecek sc->sk_rboff = SK_RBOFF_0; 1661 1.1 jdolecek break; 1662 1.1 jdolecek default: 1663 1.51 christos aprint_error_dev(sc->sk_dev, "unknown ram size: %d\n", 1664 1.48 cegger val); 1665 1.28 riz goto fail_1; 1666 1.1 jdolecek break; 1667 1.1 jdolecek } 1668 1.1 jdolecek 1669 1.1 jdolecek DPRINTFN(2, ("skc_attach: ramsize=%d(%dk), rboff=%d\n", 1670 1.1 jdolecek sc->sk_ramsize, sc->sk_ramsize / 1024, 1671 1.1 jdolecek sc->sk_rboff)); 1672 1.1 jdolecek } else { 1673 1.92 msaitoh uint8_t val = sk_win_read_1(sc, SK_EPROM0); 1674 1.11 skd sc->sk_ramsize = ( val == 0 ) ? 0x20000 : (( val * 4 )*1024); 1675 1.1 jdolecek sc->sk_rboff = SK_RBOFF_0; 1676 1.1 jdolecek 1677 1.1 jdolecek DPRINTFN(2, ("skc_attach: ramsize=%dk (%d), rboff=%d\n", 1678 1.1 jdolecek sc->sk_ramsize / 1024, sc->sk_ramsize, 1679 1.1 jdolecek sc->sk_rboff)); 1680 1.1 jdolecek } 1681 1.1 jdolecek 1682 1.1 jdolecek /* Read and save physical media type */ 1683 1.31 riz switch (sk_win_read_1(sc, SK_PMDTYPE)) { 1684 1.1 jdolecek case SK_PMD_1000BASESX: 1685 1.1 jdolecek sc->sk_pmd = IFM_1000_SX; 1686 1.1 jdolecek break; 1687 1.1 jdolecek case SK_PMD_1000BASELX: 1688 1.1 jdolecek sc->sk_pmd = IFM_1000_LX; 1689 1.1 jdolecek break; 1690 1.1 jdolecek case SK_PMD_1000BASECX: 1691 1.1 jdolecek sc->sk_pmd = IFM_1000_CX; 1692 1.1 jdolecek break; 1693 1.1 jdolecek case SK_PMD_1000BASETX: 1694 1.26 riz case SK_PMD_1000BASETX_ALT: 1695 1.1 jdolecek sc->sk_pmd = IFM_1000_T; 1696 1.1 jdolecek break; 1697 1.1 jdolecek default: 1698 1.51 christos aprint_error_dev(sc->sk_dev, "unknown media type: 0x%x\n", 1699 1.48 cegger sk_win_read_1(sc, SK_PMDTYPE)); 1700 1.28 riz goto fail_1; 1701 1.1 jdolecek } 1702 1.1 jdolecek 1703 1.11 skd /* determine whether to name it with vpd or just make it up */ 1704 1.11 skd /* Marvell Yukon VPD's can freqently be bogus */ 1705 1.11 skd 1706 1.11 skd switch (pa->pa_id) { 1707 1.11 skd case PCI_ID_CODE(PCI_VENDOR_SCHNEIDERKOCH, 1708 1.11 skd PCI_PRODUCT_SCHNEIDERKOCH_SKNET_GE): 1709 1.11 skd case PCI_PRODUCT_SCHNEIDERKOCH_SK9821v2: 1710 1.11 skd case PCI_PRODUCT_3COM_3C940: 1711 1.11 skd case PCI_PRODUCT_DLINK_DGE530T: 1712 1.26 riz case PCI_PRODUCT_DLINK_DGE560T: 1713 1.26 riz case PCI_PRODUCT_DLINK_DGE560T_2: 1714 1.11 skd case PCI_PRODUCT_LINKSYS_EG1032: 1715 1.11 skd case PCI_PRODUCT_LINKSYS_EG1064: 1716 1.11 skd case PCI_ID_CODE(PCI_VENDOR_SCHNEIDERKOCH, 1717 1.11 skd PCI_PRODUCT_SCHNEIDERKOCH_SK9821v2): 1718 1.96 msaitoh case PCI_ID_CODE(PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C940): 1719 1.96 msaitoh case PCI_ID_CODE(PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE530T): 1720 1.96 msaitoh case PCI_ID_CODE(PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE560T): 1721 1.96 msaitoh case PCI_ID_CODE(PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE560T_2): 1722 1.96 msaitoh case PCI_ID_CODE(PCI_VENDOR_LINKSYS, PCI_PRODUCT_LINKSYS_EG1032): 1723 1.96 msaitoh case PCI_ID_CODE(PCI_VENDOR_LINKSYS, PCI_PRODUCT_LINKSYS_EG1064): 1724 1.92 msaitoh sc->sk_name = sc->sk_vpd_prodname; 1725 1.92 msaitoh break; 1726 1.96 msaitoh case PCI_ID_CODE(PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_SKNET): 1727 1.11 skd /* whoops yukon vpd prodname bears no resemblance to reality */ 1728 1.11 skd switch (sc->sk_type) { 1729 1.11 skd case SK_GENESIS: 1730 1.11 skd sc->sk_name = sc->sk_vpd_prodname; 1731 1.11 skd break; 1732 1.11 skd case SK_YUKON: 1733 1.11 skd sc->sk_name = "Marvell Yukon Gigabit Ethernet"; 1734 1.11 skd break; 1735 1.11 skd case SK_YUKON_LITE: 1736 1.11 skd sc->sk_name = "Marvell Yukon Lite Gigabit Ethernet"; 1737 1.11 skd break; 1738 1.11 skd case SK_YUKON_LP: 1739 1.11 skd sc->sk_name = "Marvell Yukon LP Gigabit Ethernet"; 1740 1.11 skd break; 1741 1.11 skd default: 1742 1.11 skd sc->sk_name = "Marvell Yukon (Unknown) Gigabit Ethernet"; 1743 1.11 skd } 1744 1.11 skd 1745 1.11 skd /* Yukon Lite Rev A0 needs special test, from sk98lin driver */ 1746 1.11 skd 1747 1.11 skd if ( sc->sk_type == SK_YUKON ) { 1748 1.11 skd uint32_t flashaddr; 1749 1.11 skd uint8_t testbyte; 1750 1.14 perry 1751 1.96 msaitoh flashaddr = sk_win_read_4(sc, SK_EP_ADDR); 1752 1.14 perry 1753 1.11 skd /* test Flash-Address Register */ 1754 1.96 msaitoh sk_win_write_1(sc, SK_EP_ADDR+3, 0xff); 1755 1.11 skd testbyte = sk_win_read_1(sc, SK_EP_ADDR+3); 1756 1.14 perry 1757 1.11 skd if (testbyte != 0) { 1758 1.11 skd /* this is yukon lite Rev. A0 */ 1759 1.11 skd sc->sk_type = SK_YUKON_LITE; 1760 1.11 skd sc->sk_rev = SK_YUKON_LITE_REV_A0; 1761 1.11 skd /* restore Flash-Address Register */ 1762 1.96 msaitoh sk_win_write_4(sc, SK_EP_ADDR, flashaddr); 1763 1.11 skd } 1764 1.11 skd } 1765 1.11 skd break; 1766 1.96 msaitoh case PCI_ID_CODE(PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_BELKIN): 1767 1.13 fredb sc->sk_name = sc->sk_vpd_prodname; 1768 1.13 fredb break; 1769 1.92 msaitoh default: 1770 1.21 wiz sc->sk_name = "Unknown Marvell"; 1771 1.11 skd } 1772 1.11 skd 1773 1.14 perry 1774 1.11 skd if ( sc->sk_type == SK_YUKON_LITE ) { 1775 1.11 skd switch (sc->sk_rev) { 1776 1.11 skd case SK_YUKON_LITE_REV_A0: 1777 1.11 skd revstr = "A0"; 1778 1.11 skd break; 1779 1.11 skd case SK_YUKON_LITE_REV_A1: 1780 1.11 skd revstr = "A1"; 1781 1.11 skd break; 1782 1.11 skd case SK_YUKON_LITE_REV_A3: 1783 1.11 skd revstr = "A3"; 1784 1.11 skd break; 1785 1.11 skd default: 1786 1.11 skd revstr = ""; 1787 1.11 skd } 1788 1.11 skd } else { 1789 1.11 skd revstr = ""; 1790 1.11 skd } 1791 1.11 skd 1792 1.1 jdolecek /* Announce the product name. */ 1793 1.51 christos aprint_normal_dev(sc->sk_dev, "%s rev. %s(0x%x)\n", 1794 1.11 skd sc->sk_name, revstr, sc->sk_rev); 1795 1.1 jdolecek 1796 1.1 jdolecek skca.skc_port = SK_PORT_A; 1797 1.109 thorpej (void)config_found(sc->sk_dev, &skca, skcprint, CFARGS_NONE); 1798 1.1 jdolecek 1799 1.1 jdolecek if (!(sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC)) { 1800 1.1 jdolecek skca.skc_port = SK_PORT_B; 1801 1.109 thorpej (void)config_found(sc->sk_dev, &skca, skcprint, CFARGS_NONE); 1802 1.1 jdolecek } 1803 1.1 jdolecek 1804 1.1 jdolecek /* Turn on the 'driver is loaded' LED. */ 1805 1.1 jdolecek CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_ON); 1806 1.1 jdolecek 1807 1.20 riz /* skc sysctl setup */ 1808 1.20 riz 1809 1.20 riz sc->sk_int_mod = SK_IM_DEFAULT; 1810 1.20 riz sc->sk_int_mod_pending = 0; 1811 1.20 riz 1812 1.20 riz if ((rc = sysctl_createv(&sc->sk_clog, 0, NULL, &node, 1813 1.51 christos 0, CTLTYPE_NODE, device_xname(sc->sk_dev), 1814 1.20 riz SYSCTL_DESCR("skc per-controller controls"), 1815 1.20 riz NULL, 0, NULL, 0, CTL_HW, sk_root_num, CTL_CREATE, 1816 1.20 riz CTL_EOL)) != 0) { 1817 1.51 christos aprint_normal_dev(sc->sk_dev, "couldn't create sysctl node\n"); 1818 1.28 riz goto fail_1; 1819 1.20 riz } 1820 1.20 riz 1821 1.20 riz sk_nodenum = node->sysctl_num; 1822 1.20 riz 1823 1.20 riz /* interrupt moderation time in usecs */ 1824 1.20 riz if ((rc = sysctl_createv(&sc->sk_clog, 0, NULL, &node, 1825 1.20 riz CTLFLAG_READWRITE, 1826 1.20 riz CTLTYPE_INT, "int_mod", 1827 1.20 riz SYSCTL_DESCR("sk interrupt moderation timer"), 1828 1.71 dsl sk_sysctl_handler, 0, (void *)sc, 1829 1.20 riz 0, CTL_HW, sk_root_num, sk_nodenum, CTL_CREATE, 1830 1.20 riz CTL_EOL)) != 0) { 1831 1.100 msaitoh aprint_normal_dev(sc->sk_dev, 1832 1.100 msaitoh "couldn't create int_mod sysctl node\n"); 1833 1.28 riz goto fail_1; 1834 1.20 riz } 1835 1.20 riz 1836 1.60 kefren if (!pmf_device_register(self, skc_suspend, skc_resume)) 1837 1.60 kefren aprint_error_dev(self, "couldn't establish power handler\n"); 1838 1.60 kefren 1839 1.28 riz return; 1840 1.28 riz 1841 1.28 riz fail_1: 1842 1.28 riz pci_intr_disestablish(pc, sc->sk_intrhand); 1843 1.1 jdolecek fail: 1844 1.28 riz bus_space_unmap(sc->sk_btag, sc->sk_bhandle, iosize); 1845 1.1 jdolecek } 1846 1.1 jdolecek 1847 1.102 maxv static int 1848 1.91 msaitoh sk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, uint32_t *txidx) 1849 1.1 jdolecek { 1850 1.1 jdolecek struct sk_softc *sc = sc_if->sk_softc; 1851 1.1 jdolecek struct sk_tx_desc *f = NULL; 1852 1.91 msaitoh uint32_t frag, cur, cnt = 0, sk_ctl; 1853 1.1 jdolecek int i; 1854 1.1 jdolecek struct sk_txmap_entry *entry; 1855 1.1 jdolecek bus_dmamap_t txmap; 1856 1.1 jdolecek 1857 1.1 jdolecek DPRINTFN(3, ("sk_encap\n")); 1858 1.1 jdolecek 1859 1.11 skd entry = SIMPLEQ_FIRST(&sc_if->sk_txmap_head); 1860 1.1 jdolecek if (entry == NULL) { 1861 1.1 jdolecek DPRINTFN(3, ("sk_encap: no txmap available\n")); 1862 1.1 jdolecek return ENOBUFS; 1863 1.1 jdolecek } 1864 1.1 jdolecek txmap = entry->dmamap; 1865 1.1 jdolecek 1866 1.1 jdolecek cur = frag = *txidx; 1867 1.1 jdolecek 1868 1.1 jdolecek #ifdef SK_DEBUG 1869 1.1 jdolecek if (skdebug >= 3) 1870 1.1 jdolecek sk_dump_mbuf(m_head); 1871 1.1 jdolecek #endif 1872 1.1 jdolecek 1873 1.1 jdolecek /* 1874 1.1 jdolecek * Start packing the mbufs in this chain into 1875 1.1 jdolecek * the fragment pointers. Stop when we run out 1876 1.1 jdolecek * of fragments or hit the end of the mbuf chain. 1877 1.1 jdolecek */ 1878 1.1 jdolecek if (bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head, 1879 1.1 jdolecek BUS_DMA_NOWAIT)) { 1880 1.1 jdolecek DPRINTFN(1, ("sk_encap: dmamap failed\n")); 1881 1.31 riz return ENOBUFS; 1882 1.1 jdolecek } 1883 1.1 jdolecek 1884 1.1 jdolecek DPRINTFN(3, ("sk_encap: dm_nsegs=%d\n", txmap->dm_nsegs)); 1885 1.1 jdolecek 1886 1.3 briggs /* Sync the DMA map. */ 1887 1.3 briggs bus_dmamap_sync(sc->sc_dmatag, txmap, 0, txmap->dm_mapsize, 1888 1.3 briggs BUS_DMASYNC_PREWRITE); 1889 1.3 briggs 1890 1.1 jdolecek for (i = 0; i < txmap->dm_nsegs; i++) { 1891 1.1 jdolecek if ((SK_TX_RING_CNT - (sc_if->sk_cdata.sk_tx_cnt + cnt)) < 2) { 1892 1.1 jdolecek DPRINTFN(1, ("sk_encap: too few descriptors free\n")); 1893 1.31 riz return ENOBUFS; 1894 1.1 jdolecek } 1895 1.1 jdolecek f = &sc_if->sk_rdata->sk_tx_ring[frag]; 1896 1.29 riz f->sk_data_lo = htole32(txmap->dm_segs[i].ds_addr); 1897 1.29 riz sk_ctl = txmap->dm_segs[i].ds_len | SK_OPCODE_DEFAULT; 1898 1.1 jdolecek if (cnt == 0) 1899 1.29 riz sk_ctl |= SK_TXCTL_FIRSTFRAG; 1900 1.1 jdolecek else 1901 1.29 riz sk_ctl |= SK_TXCTL_OWN; 1902 1.29 riz f->sk_ctl = htole32(sk_ctl); 1903 1.1 jdolecek cur = frag; 1904 1.1 jdolecek SK_INC(frag, SK_TX_RING_CNT); 1905 1.1 jdolecek cnt++; 1906 1.1 jdolecek } 1907 1.1 jdolecek 1908 1.1 jdolecek sc_if->sk_cdata.sk_tx_chain[cur].sk_mbuf = m_head; 1909 1.11 skd SIMPLEQ_REMOVE_HEAD(&sc_if->sk_txmap_head, link); 1910 1.11 skd 1911 1.1 jdolecek sc_if->sk_cdata.sk_tx_map[cur] = entry; 1912 1.1 jdolecek sc_if->sk_rdata->sk_tx_ring[cur].sk_ctl |= 1913 1.96 msaitoh htole32(SK_TXCTL_LASTFRAG | SK_TXCTL_EOF_INTR); 1914 1.3 briggs 1915 1.3 briggs /* Sync descriptors before handing to chip */ 1916 1.3 briggs SK_CDTXSYNC(sc_if, *txidx, txmap->dm_nsegs, 1917 1.96 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1918 1.3 briggs 1919 1.29 riz sc_if->sk_rdata->sk_tx_ring[*txidx].sk_ctl |= 1920 1.29 riz htole32(SK_TXCTL_OWN); 1921 1.3 briggs 1922 1.3 briggs /* Sync first descriptor to hand it off */ 1923 1.96 msaitoh SK_CDTXSYNC(sc_if, *txidx, 1, 1924 1.96 msaitoh BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1925 1.3 briggs 1926 1.1 jdolecek sc_if->sk_cdata.sk_tx_cnt += cnt; 1927 1.1 jdolecek 1928 1.1 jdolecek #ifdef SK_DEBUG 1929 1.1 jdolecek if (skdebug >= 3) { 1930 1.1 jdolecek struct sk_tx_desc *desc; 1931 1.91 msaitoh uint32_t idx; 1932 1.1 jdolecek for (idx = *txidx; idx != frag; SK_INC(idx, SK_TX_RING_CNT)) { 1933 1.1 jdolecek desc = &sc_if->sk_rdata->sk_tx_ring[idx]; 1934 1.1 jdolecek sk_dump_txdesc(desc, idx); 1935 1.1 jdolecek } 1936 1.1 jdolecek } 1937 1.1 jdolecek #endif 1938 1.1 jdolecek 1939 1.1 jdolecek *txidx = frag; 1940 1.1 jdolecek 1941 1.1 jdolecek DPRINTFN(3, ("sk_encap: completed successfully\n")); 1942 1.1 jdolecek 1943 1.31 riz return 0; 1944 1.1 jdolecek } 1945 1.1 jdolecek 1946 1.102 maxv static void 1947 1.1 jdolecek sk_start(struct ifnet *ifp) 1948 1.1 jdolecek { 1949 1.92 msaitoh struct sk_if_softc *sc_if = ifp->if_softc; 1950 1.92 msaitoh struct sk_softc *sc = sc_if->sk_softc; 1951 1.92 msaitoh struct mbuf *m_head = NULL; 1952 1.92 msaitoh uint32_t idx = sc_if->sk_cdata.sk_tx_prod; 1953 1.1 jdolecek int pkts = 0; 1954 1.1 jdolecek 1955 1.3 briggs DPRINTFN(3, ("sk_start (idx %d, tx_chain[idx] %p)\n", idx, 1956 1.3 briggs sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf)); 1957 1.1 jdolecek 1958 1.31 riz while (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf == NULL) { 1959 1.1 jdolecek IFQ_POLL(&ifp->if_snd, m_head); 1960 1.1 jdolecek if (m_head == NULL) 1961 1.1 jdolecek break; 1962 1.1 jdolecek 1963 1.1 jdolecek /* 1964 1.1 jdolecek * Pack the data into the transmit ring. If we 1965 1.1 jdolecek * don't have room, set the OACTIVE flag and wait 1966 1.1 jdolecek * for the NIC to drain the ring. 1967 1.1 jdolecek */ 1968 1.1 jdolecek if (sk_encap(sc_if, m_head, &idx)) { 1969 1.1 jdolecek ifp->if_flags |= IFF_OACTIVE; 1970 1.1 jdolecek break; 1971 1.1 jdolecek } 1972 1.1 jdolecek 1973 1.1 jdolecek /* now we are committed to transmit the packet */ 1974 1.1 jdolecek IFQ_DEQUEUE(&ifp->if_snd, m_head); 1975 1.1 jdolecek pkts++; 1976 1.1 jdolecek 1977 1.1 jdolecek /* 1978 1.1 jdolecek * If there's a BPF listener, bounce a copy of this frame 1979 1.1 jdolecek * to him. 1980 1.1 jdolecek */ 1981 1.87 msaitoh bpf_mtap(ifp, m_head, BPF_D_OUT); 1982 1.1 jdolecek } 1983 1.1 jdolecek if (pkts == 0) 1984 1.1 jdolecek return; 1985 1.1 jdolecek 1986 1.1 jdolecek /* Transmit */ 1987 1.17 riz if (idx != sc_if->sk_cdata.sk_tx_prod) { 1988 1.17 riz sc_if->sk_cdata.sk_tx_prod = idx; 1989 1.17 riz CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_START); 1990 1.1 jdolecek 1991 1.17 riz /* Set a timeout in case the chip goes out to lunch. */ 1992 1.17 riz ifp->if_timer = 5; 1993 1.17 riz } 1994 1.1 jdolecek } 1995 1.1 jdolecek 1996 1.1 jdolecek 1997 1.102 maxv static void 1998 1.1 jdolecek sk_watchdog(struct ifnet *ifp) 1999 1.1 jdolecek { 2000 1.1 jdolecek struct sk_if_softc *sc_if = ifp->if_softc; 2001 1.1 jdolecek 2002 1.32 riz /* 2003 1.32 riz * Reclaim first as there is a possibility of losing Tx completion 2004 1.32 riz * interrupts. 2005 1.32 riz */ 2006 1.32 riz sk_txeof(sc_if); 2007 1.32 riz if (sc_if->sk_cdata.sk_tx_cnt != 0) { 2008 1.51 christos aprint_error_dev(sc_if->sk_dev, "watchdog timeout\n"); 2009 1.32 riz 2010 1.104 thorpej if_statinc(ifp, if_oerrors); 2011 1.32 riz 2012 1.32 riz sk_init(ifp); 2013 1.32 riz } 2014 1.1 jdolecek } 2015 1.1 jdolecek 2016 1.102 maxv #if 0 /* XXX XXX XXX UNUSED */ 2017 1.102 maxv static void 2018 1.37 christos sk_shutdown(void *v) 2019 1.1 jdolecek { 2020 1.1 jdolecek struct sk_if_softc *sc_if = (struct sk_if_softc *)v; 2021 1.1 jdolecek struct sk_softc *sc = sc_if->sk_softc; 2022 1.92 msaitoh struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; 2023 1.1 jdolecek 2024 1.1 jdolecek DPRINTFN(2, ("sk_shutdown\n")); 2025 1.96 msaitoh sk_stop(ifp, 1); 2026 1.1 jdolecek 2027 1.1 jdolecek /* Turn off the 'driver is loaded' LED. */ 2028 1.1 jdolecek CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_OFF); 2029 1.1 jdolecek 2030 1.1 jdolecek /* 2031 1.1 jdolecek * Reset the GEnesis controller. Doing this should also 2032 1.1 jdolecek * assert the resets on the attached XMAC(s). 2033 1.1 jdolecek */ 2034 1.1 jdolecek sk_reset(sc); 2035 1.1 jdolecek } 2036 1.102 maxv #endif 2037 1.1 jdolecek 2038 1.102 maxv static void 2039 1.1 jdolecek sk_rxeof(struct sk_if_softc *sc_if) 2040 1.1 jdolecek { 2041 1.1 jdolecek struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; 2042 1.1 jdolecek struct mbuf *m; 2043 1.1 jdolecek struct sk_chain *cur_rx; 2044 1.1 jdolecek struct sk_rx_desc *cur_desc; 2045 1.1 jdolecek int i, cur, total_len = 0; 2046 1.91 msaitoh uint32_t rxstat, sk_ctl; 2047 1.1 jdolecek bus_dmamap_t dmamap; 2048 1.1 jdolecek 2049 1.3 briggs i = sc_if->sk_cdata.sk_rx_prod; 2050 1.1 jdolecek 2051 1.3 briggs DPRINTFN(3, ("sk_rxeof %d\n", i)); 2052 1.1 jdolecek 2053 1.3 briggs for (;;) { 2054 1.1 jdolecek cur = i; 2055 1.3 briggs 2056 1.3 briggs /* Sync the descriptor */ 2057 1.3 briggs SK_CDRXSYNC(sc_if, cur, 2058 1.96 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2059 1.3 briggs 2060 1.29 riz sk_ctl = le32toh(sc_if->sk_rdata->sk_rx_ring[cur].sk_ctl); 2061 1.29 riz if (sk_ctl & SK_RXCTL_OWN) { 2062 1.3 briggs /* Invalidate the descriptor -- it's not ready yet */ 2063 1.3 briggs SK_CDRXSYNC(sc_if, cur, BUS_DMASYNC_PREREAD); 2064 1.3 briggs sc_if->sk_cdata.sk_rx_prod = i; 2065 1.3 briggs break; 2066 1.3 briggs } 2067 1.3 briggs 2068 1.1 jdolecek cur_rx = &sc_if->sk_cdata.sk_rx_chain[cur]; 2069 1.1 jdolecek cur_desc = &sc_if->sk_rdata->sk_rx_ring[cur]; 2070 1.22 riz dmamap = sc_if->sk_cdata.sk_rx_jumbo_map; 2071 1.3 briggs 2072 1.3 briggs bus_dmamap_sync(sc_if->sk_softc->sc_dmatag, dmamap, 0, 2073 1.3 briggs dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); 2074 1.1 jdolecek 2075 1.29 riz rxstat = le32toh(cur_desc->sk_xmac_rxstat); 2076 1.1 jdolecek m = cur_rx->sk_mbuf; 2077 1.1 jdolecek cur_rx->sk_mbuf = NULL; 2078 1.29 riz total_len = SK_RXBYTES(le32toh(cur_desc->sk_ctl)); 2079 1.1 jdolecek 2080 1.1 jdolecek sc_if->sk_cdata.sk_rx_map[cur] = 0; 2081 1.1 jdolecek 2082 1.1 jdolecek SK_INC(i, SK_RX_RING_CNT); 2083 1.1 jdolecek 2084 1.1 jdolecek if (rxstat & XM_RXSTAT_ERRFRAME) { 2085 1.104 thorpej if_statinc(ifp, if_ierrors); 2086 1.1 jdolecek sk_newbuf(sc_if, cur, m, dmamap); 2087 1.1 jdolecek continue; 2088 1.1 jdolecek } 2089 1.1 jdolecek 2090 1.1 jdolecek /* 2091 1.1 jdolecek * Try to allocate a new jumbo buffer. If that 2092 1.1 jdolecek * fails, copy the packet to mbufs and put the 2093 1.1 jdolecek * jumbo buffer back in the ring so it can be 2094 1.1 jdolecek * re-used. If allocating mbufs fails, then we 2095 1.1 jdolecek * have to drop the packet. 2096 1.1 jdolecek */ 2097 1.1 jdolecek if (sk_newbuf(sc_if, cur, NULL, dmamap) == ENOBUFS) { 2098 1.1 jdolecek struct mbuf *m0; 2099 1.1 jdolecek m0 = m_devget(mtod(m, char *) - ETHER_ALIGN, 2100 1.90 maxv total_len + ETHER_ALIGN, 0, ifp); 2101 1.1 jdolecek sk_newbuf(sc_if, cur, m, dmamap); 2102 1.1 jdolecek if (m0 == NULL) { 2103 1.51 christos aprint_error_dev(sc_if->sk_dev, "no receive " 2104 1.51 christos "buffers available -- packet dropped!\n"); 2105 1.104 thorpej if_statinc(ifp, if_ierrors); 2106 1.1 jdolecek continue; 2107 1.1 jdolecek } 2108 1.1 jdolecek m_adj(m0, ETHER_ALIGN); 2109 1.1 jdolecek m = m0; 2110 1.1 jdolecek } else { 2111 1.82 ozaki m_set_rcvif(m, ifp); 2112 1.1 jdolecek m->m_pkthdr.len = m->m_len = total_len; 2113 1.1 jdolecek } 2114 1.1 jdolecek 2115 1.1 jdolecek /* pass it on. */ 2116 1.81 ozaki if_percpuq_enqueue(ifp->if_percpuq, m); 2117 1.1 jdolecek } 2118 1.1 jdolecek } 2119 1.1 jdolecek 2120 1.102 maxv static void 2121 1.1 jdolecek sk_txeof(struct sk_if_softc *sc_if) 2122 1.1 jdolecek { 2123 1.1 jdolecek struct sk_softc *sc = sc_if->sk_softc; 2124 1.17 riz struct sk_tx_desc *cur_tx; 2125 1.1 jdolecek struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; 2126 1.91 msaitoh uint32_t idx, sk_ctl; 2127 1.1 jdolecek struct sk_txmap_entry *entry; 2128 1.1 jdolecek 2129 1.1 jdolecek DPRINTFN(3, ("sk_txeof\n")); 2130 1.1 jdolecek 2131 1.1 jdolecek /* 2132 1.1 jdolecek * Go through our tx ring and free mbufs for those 2133 1.1 jdolecek * frames that have been sent. 2134 1.1 jdolecek */ 2135 1.1 jdolecek idx = sc_if->sk_cdata.sk_tx_cons; 2136 1.31 riz while (idx != sc_if->sk_cdata.sk_tx_prod) { 2137 1.5 briggs SK_CDTXSYNC(sc_if, idx, 1, 2138 1.96 msaitoh BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2139 1.3 briggs 2140 1.1 jdolecek cur_tx = &sc_if->sk_rdata->sk_tx_ring[idx]; 2141 1.29 riz sk_ctl = le32toh(cur_tx->sk_ctl); 2142 1.1 jdolecek #ifdef SK_DEBUG 2143 1.1 jdolecek if (skdebug >= 3) 2144 1.1 jdolecek sk_dump_txdesc(cur_tx, idx); 2145 1.1 jdolecek #endif 2146 1.29 riz if (sk_ctl & SK_TXCTL_OWN) { 2147 1.5 briggs SK_CDTXSYNC(sc_if, idx, 1, BUS_DMASYNC_PREREAD); 2148 1.1 jdolecek break; 2149 1.3 briggs } 2150 1.29 riz if (sk_ctl & SK_TXCTL_LASTFRAG) 2151 1.104 thorpej if_statinc(ifp, if_opackets); 2152 1.1 jdolecek if (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf != NULL) { 2153 1.5 briggs entry = sc_if->sk_cdata.sk_tx_map[idx]; 2154 1.5 briggs 2155 1.1 jdolecek bus_dmamap_sync(sc->sc_dmatag, entry->dmamap, 0, 2156 1.1 jdolecek entry->dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); 2157 1.1 jdolecek 2158 1.1 jdolecek bus_dmamap_unload(sc->sc_dmatag, entry->dmamap); 2159 1.11 skd SIMPLEQ_INSERT_TAIL(&sc_if->sk_txmap_head, entry, 2160 1.1 jdolecek link); 2161 1.1 jdolecek sc_if->sk_cdata.sk_tx_map[idx] = NULL; 2162 1.111 rin 2163 1.111 rin m_freem(sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf); 2164 1.111 rin sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf = NULL; 2165 1.1 jdolecek } 2166 1.1 jdolecek sc_if->sk_cdata.sk_tx_cnt--; 2167 1.1 jdolecek SK_INC(idx, SK_TX_RING_CNT); 2168 1.5 briggs } 2169 1.5 briggs if (sc_if->sk_cdata.sk_tx_cnt == 0) 2170 1.1 jdolecek ifp->if_timer = 0; 2171 1.11 skd else /* nudge chip to keep tx ring moving */ 2172 1.11 skd CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_START); 2173 1.1 jdolecek 2174 1.17 riz if (sc_if->sk_cdata.sk_tx_cnt < SK_TX_RING_CNT - 2) 2175 1.17 riz ifp->if_flags &= ~IFF_OACTIVE; 2176 1.17 riz 2177 1.1 jdolecek sc_if->sk_cdata.sk_tx_cons = idx; 2178 1.1 jdolecek } 2179 1.1 jdolecek 2180 1.102 maxv static void 2181 1.1 jdolecek sk_tick(void *xsc_if) 2182 1.1 jdolecek { 2183 1.1 jdolecek struct sk_if_softc *sc_if = xsc_if; 2184 1.1 jdolecek struct mii_data *mii = &sc_if->sk_mii; 2185 1.1 jdolecek struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; 2186 1.1 jdolecek int i; 2187 1.1 jdolecek 2188 1.1 jdolecek DPRINTFN(3, ("sk_tick\n")); 2189 1.1 jdolecek 2190 1.1 jdolecek if (!(ifp->if_flags & IFF_UP)) 2191 1.1 jdolecek return; 2192 1.1 jdolecek 2193 1.1 jdolecek if (sc_if->sk_phytype == SK_PHYTYPE_BCOM) { 2194 1.1 jdolecek sk_intr_bcom(sc_if); 2195 1.1 jdolecek return; 2196 1.1 jdolecek } 2197 1.1 jdolecek 2198 1.1 jdolecek /* 2199 1.1 jdolecek * According to SysKonnect, the correct way to verify that 2200 1.1 jdolecek * the link has come back up is to poll bit 0 of the GPIO 2201 1.1 jdolecek * register three times. This pin has the signal from the 2202 1.1 jdolecek * link sync pin connected to it; if we read the same link 2203 1.1 jdolecek * state 3 times in a row, we know the link is up. 2204 1.1 jdolecek */ 2205 1.1 jdolecek for (i = 0; i < 3; i++) { 2206 1.1 jdolecek if (SK_XM_READ_2(sc_if, XM_GPIO) & XM_GPIO_GP0_SET) 2207 1.1 jdolecek break; 2208 1.1 jdolecek } 2209 1.1 jdolecek 2210 1.1 jdolecek if (i != 3) { 2211 1.1 jdolecek callout_reset(&sc_if->sk_tick_ch, hz, sk_tick, sc_if); 2212 1.1 jdolecek return; 2213 1.1 jdolecek } 2214 1.1 jdolecek 2215 1.1 jdolecek /* Turn the GP0 interrupt back on. */ 2216 1.1 jdolecek SK_XM_CLRBIT_2(sc_if, XM_IMR, XM_IMR_GP0_SET); 2217 1.1 jdolecek SK_XM_READ_2(sc_if, XM_ISR); 2218 1.1 jdolecek mii_tick(mii); 2219 1.79 christos if (ifp->if_link_state != LINK_STATE_UP) 2220 1.79 christos callout_reset(&sc_if->sk_tick_ch, hz, sk_tick, sc_if); 2221 1.79 christos else 2222 1.79 christos callout_stop(&sc_if->sk_tick_ch); 2223 1.1 jdolecek } 2224 1.1 jdolecek 2225 1.102 maxv static void 2226 1.1 jdolecek sk_intr_bcom(struct sk_if_softc *sc_if) 2227 1.1 jdolecek { 2228 1.1 jdolecek struct mii_data *mii = &sc_if->sk_mii; 2229 1.1 jdolecek struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; 2230 1.93 msaitoh uint16_t status; 2231 1.1 jdolecek 2232 1.1 jdolecek 2233 1.1 jdolecek DPRINTFN(3, ("sk_intr_bcom\n")); 2234 1.1 jdolecek 2235 1.96 msaitoh SK_XM_CLRBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_TX_ENB | XM_MMUCMD_RX_ENB); 2236 1.1 jdolecek 2237 1.1 jdolecek /* 2238 1.1 jdolecek * Read the PHY interrupt register to make sure 2239 1.1 jdolecek * we clear any pending interrupts. 2240 1.1 jdolecek */ 2241 1.93 msaitoh sk_xmac_miibus_readreg(sc_if->sk_dev, 2242 1.93 msaitoh SK_PHYADDR_BCOM, BRGPHY_MII_ISR, &status); 2243 1.1 jdolecek 2244 1.1 jdolecek if (!(ifp->if_flags & IFF_RUNNING)) { 2245 1.1 jdolecek sk_init_xmac(sc_if); 2246 1.1 jdolecek return; 2247 1.1 jdolecek } 2248 1.1 jdolecek 2249 1.96 msaitoh if (status & (BRGPHY_ISR_LNK_CHG | BRGPHY_ISR_AN_PR)) { 2250 1.93 msaitoh uint16_t lstat; 2251 1.93 msaitoh sk_xmac_miibus_readreg(sc_if->sk_dev, 2252 1.93 msaitoh SK_PHYADDR_BCOM, BRGPHY_MII_AUXSTS, &lstat); 2253 1.1 jdolecek 2254 1.1 jdolecek if (!(lstat & BRGPHY_AUXSTS_LINK) && sc_if->sk_link) { 2255 1.46 dyoung (void)mii_mediachg(mii); 2256 1.1 jdolecek /* Turn off the link LED. */ 2257 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, 2258 1.1 jdolecek SK_LINKLED1_CTL, SK_LINKLED_OFF); 2259 1.1 jdolecek sc_if->sk_link = 0; 2260 1.1 jdolecek } else if (status & BRGPHY_ISR_LNK_CHG) { 2261 1.52 christos sk_xmac_miibus_writereg(sc_if->sk_dev, 2262 1.1 jdolecek SK_PHYADDR_BCOM, BRGPHY_MII_IMR, 0xFF00); 2263 1.1 jdolecek mii_tick(mii); 2264 1.1 jdolecek sc_if->sk_link = 1; 2265 1.1 jdolecek /* Turn on the link LED. */ 2266 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, 2267 1.96 msaitoh SK_LINKLED_ON | SK_LINKLED_LINKSYNC_OFF | 2268 1.1 jdolecek SK_LINKLED_BLINK_OFF); 2269 1.1 jdolecek mii_pollstat(mii); 2270 1.1 jdolecek } else { 2271 1.1 jdolecek mii_tick(mii); 2272 1.96 msaitoh callout_reset(&sc_if->sk_tick_ch, hz, sk_tick, sc_if); 2273 1.1 jdolecek } 2274 1.1 jdolecek } 2275 1.1 jdolecek 2276 1.96 msaitoh SK_XM_SETBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_TX_ENB | XM_MMUCMD_RX_ENB); 2277 1.1 jdolecek } 2278 1.1 jdolecek 2279 1.102 maxv static void 2280 1.1 jdolecek sk_intr_xmac(struct sk_if_softc *sc_if) 2281 1.1 jdolecek { 2282 1.91 msaitoh uint16_t status = SK_XM_READ_2(sc_if, XM_ISR); 2283 1.1 jdolecek 2284 1.1 jdolecek DPRINTFN(3, ("sk_intr_xmac\n")); 2285 1.1 jdolecek 2286 1.1 jdolecek if (sc_if->sk_phytype == SK_PHYTYPE_XMAC) { 2287 1.1 jdolecek if (status & XM_ISR_GP0_SET) { 2288 1.1 jdolecek SK_XM_SETBIT_2(sc_if, XM_IMR, XM_IMR_GP0_SET); 2289 1.1 jdolecek callout_reset(&sc_if->sk_tick_ch, hz, sk_tick, sc_if); 2290 1.1 jdolecek } 2291 1.1 jdolecek 2292 1.1 jdolecek if (status & XM_ISR_AUTONEG_DONE) { 2293 1.1 jdolecek callout_reset(&sc_if->sk_tick_ch, hz, sk_tick, sc_if); 2294 1.1 jdolecek } 2295 1.1 jdolecek } 2296 1.1 jdolecek 2297 1.1 jdolecek if (status & XM_IMR_TX_UNDERRUN) 2298 1.1 jdolecek SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_FLUSH_TXFIFO); 2299 1.1 jdolecek 2300 1.1 jdolecek if (status & XM_IMR_RX_OVERRUN) 2301 1.1 jdolecek SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_FLUSH_RXFIFO); 2302 1.1 jdolecek } 2303 1.1 jdolecek 2304 1.102 maxv static void 2305 1.31 riz sk_intr_yukon(struct sk_if_softc *sc_if) 2306 1.1 jdolecek { 2307 1.75 martin #ifdef SK_DEBUG 2308 1.1 jdolecek int status; 2309 1.1 jdolecek 2310 1.92 msaitoh status = 2311 1.75 martin #endif 2312 1.75 martin SK_IF_READ_2(sc_if, 0, SK_GMAC_ISR); 2313 1.1 jdolecek 2314 1.1 jdolecek DPRINTFN(3, ("sk_intr_yukon status=%#x\n", status)); 2315 1.1 jdolecek } 2316 1.1 jdolecek 2317 1.102 maxv static int 2318 1.1 jdolecek sk_intr(void *xsc) 2319 1.1 jdolecek { 2320 1.1 jdolecek struct sk_softc *sc = xsc; 2321 1.1 jdolecek struct sk_if_softc *sc_if0 = sc->sk_if[SK_PORT_A]; 2322 1.1 jdolecek struct sk_if_softc *sc_if1 = sc->sk_if[SK_PORT_B]; 2323 1.1 jdolecek struct ifnet *ifp0 = NULL, *ifp1 = NULL; 2324 1.91 msaitoh uint32_t status; 2325 1.1 jdolecek int claimed = 0; 2326 1.1 jdolecek 2327 1.1 jdolecek if (sc_if0 != NULL) 2328 1.1 jdolecek ifp0 = &sc_if0->sk_ethercom.ec_if; 2329 1.1 jdolecek if (sc_if1 != NULL) 2330 1.1 jdolecek ifp1 = &sc_if1->sk_ethercom.ec_if; 2331 1.1 jdolecek 2332 1.1 jdolecek for (;;) { 2333 1.1 jdolecek status = CSR_READ_4(sc, SK_ISSR); 2334 1.1 jdolecek DPRINTFN(3, ("sk_intr: status=%#x\n", status)); 2335 1.1 jdolecek 2336 1.1 jdolecek if (!(status & sc->sk_intrmask)) 2337 1.1 jdolecek break; 2338 1.1 jdolecek 2339 1.1 jdolecek claimed = 1; 2340 1.1 jdolecek 2341 1.1 jdolecek /* Handle receive interrupts first. */ 2342 1.24 christos if (sc_if0 && (status & SK_ISR_RX1_EOF)) { 2343 1.1 jdolecek sk_rxeof(sc_if0); 2344 1.1 jdolecek CSR_WRITE_4(sc, SK_BMU_RX_CSR0, 2345 1.96 msaitoh SK_RXBMU_CLR_IRQ_EOF | SK_RXBMU_RX_START); 2346 1.1 jdolecek } 2347 1.24 christos if (sc_if1 && (status & SK_ISR_RX2_EOF)) { 2348 1.1 jdolecek sk_rxeof(sc_if1); 2349 1.1 jdolecek CSR_WRITE_4(sc, SK_BMU_RX_CSR1, 2350 1.96 msaitoh SK_RXBMU_CLR_IRQ_EOF | SK_RXBMU_RX_START); 2351 1.1 jdolecek } 2352 1.1 jdolecek 2353 1.1 jdolecek /* Then transmit interrupts. */ 2354 1.24 christos if (sc_if0 && (status & SK_ISR_TX1_S_EOF)) { 2355 1.1 jdolecek sk_txeof(sc_if0); 2356 1.1 jdolecek CSR_WRITE_4(sc, SK_BMU_TXS_CSR0, 2357 1.1 jdolecek SK_TXBMU_CLR_IRQ_EOF); 2358 1.1 jdolecek } 2359 1.24 christos if (sc_if1 && (status & SK_ISR_TX2_S_EOF)) { 2360 1.1 jdolecek sk_txeof(sc_if1); 2361 1.1 jdolecek CSR_WRITE_4(sc, SK_BMU_TXS_CSR1, 2362 1.1 jdolecek SK_TXBMU_CLR_IRQ_EOF); 2363 1.1 jdolecek } 2364 1.1 jdolecek 2365 1.1 jdolecek /* Then MAC interrupts. */ 2366 1.24 christos if (sc_if0 && (status & SK_ISR_MAC1) && 2367 1.23 christos (ifp0->if_flags & IFF_RUNNING)) { 2368 1.1 jdolecek if (sc->sk_type == SK_GENESIS) 2369 1.1 jdolecek sk_intr_xmac(sc_if0); 2370 1.1 jdolecek else 2371 1.1 jdolecek sk_intr_yukon(sc_if0); 2372 1.1 jdolecek } 2373 1.1 jdolecek 2374 1.24 christos if (sc_if1 && (status & SK_ISR_MAC2) && 2375 1.23 christos (ifp1->if_flags & IFF_RUNNING)) { 2376 1.1 jdolecek if (sc->sk_type == SK_GENESIS) 2377 1.1 jdolecek sk_intr_xmac(sc_if1); 2378 1.1 jdolecek else 2379 1.1 jdolecek sk_intr_yukon(sc_if1); 2380 1.1 jdolecek 2381 1.1 jdolecek } 2382 1.1 jdolecek 2383 1.1 jdolecek if (status & SK_ISR_EXTERNAL_REG) { 2384 1.24 christos if (sc_if0 != NULL && 2385 1.1 jdolecek sc_if0->sk_phytype == SK_PHYTYPE_BCOM) 2386 1.1 jdolecek sk_intr_bcom(sc_if0); 2387 1.1 jdolecek 2388 1.25 christos if (sc_if1 != NULL && 2389 1.1 jdolecek sc_if1->sk_phytype == SK_PHYTYPE_BCOM) 2390 1.1 jdolecek sk_intr_bcom(sc_if1); 2391 1.1 jdolecek } 2392 1.1 jdolecek } 2393 1.1 jdolecek 2394 1.1 jdolecek CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask); 2395 1.1 jdolecek 2396 1.83 ozaki if (ifp0 != NULL) 2397 1.83 ozaki if_schedule_deferred_start(ifp0); 2398 1.83 ozaki if (ifp1 != NULL) 2399 1.83 ozaki if_schedule_deferred_start(ifp1); 2400 1.1 jdolecek 2401 1.88 jdolecek KASSERT(sc->rnd_attached > 0); 2402 1.70 tls rnd_add_uint32(&sc->rnd_source, status); 2403 1.19 rpaulo 2404 1.20 riz if (sc->sk_int_mod_pending) 2405 1.20 riz sk_update_int_mod(sc); 2406 1.20 riz 2407 1.31 riz return claimed; 2408 1.1 jdolecek } 2409 1.1 jdolecek 2410 1.102 maxv static void 2411 1.99 msaitoh sk_unreset_xmac(struct sk_if_softc *sc_if) 2412 1.1 jdolecek { 2413 1.1 jdolecek struct sk_softc *sc = sc_if->sk_softc; 2414 1.1 jdolecek static const struct sk_bcom_hack bhack[] = { 2415 1.1 jdolecek { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 }, 2416 1.1 jdolecek { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 }, 2417 1.1 jdolecek { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 }, 2418 1.1 jdolecek { 0, 0 } }; 2419 1.1 jdolecek 2420 1.99 msaitoh DPRINTFN(1, ("sk_unreset_xmac\n")); 2421 1.1 jdolecek 2422 1.1 jdolecek /* Unreset the XMAC. */ 2423 1.1 jdolecek SK_IF_WRITE_2(sc_if, 0, SK_TXF1_MACCTL, SK_TXMACCTL_XMAC_UNRESET); 2424 1.1 jdolecek DELAY(1000); 2425 1.1 jdolecek 2426 1.1 jdolecek /* Reset the XMAC's internal state. */ 2427 1.1 jdolecek SK_XM_SETBIT_2(sc_if, XM_GPIO, XM_GPIO_RESETMAC); 2428 1.1 jdolecek 2429 1.1 jdolecek /* Save the XMAC II revision */ 2430 1.1 jdolecek sc_if->sk_xmac_rev = XM_XMAC_REV(SK_XM_READ_4(sc_if, XM_DEVID)); 2431 1.1 jdolecek 2432 1.1 jdolecek /* 2433 1.1 jdolecek * Perform additional initialization for external PHYs, 2434 1.1 jdolecek * namely for the 1000baseTX cards that use the XMAC's 2435 1.1 jdolecek * GMII mode. 2436 1.1 jdolecek */ 2437 1.1 jdolecek if (sc_if->sk_phytype == SK_PHYTYPE_BCOM) { 2438 1.1 jdolecek int i = 0; 2439 1.91 msaitoh uint32_t val; 2440 1.93 msaitoh uint16_t phyval; 2441 1.1 jdolecek 2442 1.1 jdolecek /* Take PHY out of reset. */ 2443 1.1 jdolecek val = sk_win_read_4(sc, SK_GPIO); 2444 1.1 jdolecek if (sc_if->sk_port == SK_PORT_A) 2445 1.96 msaitoh val |= SK_GPIO_DIR0 | SK_GPIO_DAT0; 2446 1.1 jdolecek else 2447 1.96 msaitoh val |= SK_GPIO_DIR2 | SK_GPIO_DAT2; 2448 1.1 jdolecek sk_win_write_4(sc, SK_GPIO, val); 2449 1.1 jdolecek 2450 1.1 jdolecek /* Enable GMII mode on the XMAC. */ 2451 1.1 jdolecek SK_XM_SETBIT_2(sc_if, XM_HWCFG, XM_HWCFG_GMIIMODE); 2452 1.1 jdolecek 2453 1.52 christos sk_xmac_miibus_writereg(sc_if->sk_dev, 2454 1.1 jdolecek SK_PHYADDR_BCOM, MII_BMCR, BMCR_RESET); 2455 1.1 jdolecek DELAY(10000); 2456 1.52 christos sk_xmac_miibus_writereg(sc_if->sk_dev, 2457 1.1 jdolecek SK_PHYADDR_BCOM, BRGPHY_MII_IMR, 0xFFF0); 2458 1.1 jdolecek 2459 1.1 jdolecek /* 2460 1.1 jdolecek * Early versions of the BCM5400 apparently have 2461 1.1 jdolecek * a bug that requires them to have their reserved 2462 1.1 jdolecek * registers initialized to some magic values. I don't 2463 1.1 jdolecek * know what the numbers do, I'm just the messenger. 2464 1.1 jdolecek */ 2465 1.93 msaitoh sk_xmac_miibus_readreg(sc_if->sk_dev, 2466 1.93 msaitoh SK_PHYADDR_BCOM, 0x03, &phyval); 2467 1.93 msaitoh if (phyval == 0x6041) { 2468 1.31 riz while (bhack[i].reg) { 2469 1.52 christos sk_xmac_miibus_writereg(sc_if->sk_dev, 2470 1.1 jdolecek SK_PHYADDR_BCOM, bhack[i].reg, 2471 1.1 jdolecek bhack[i].val); 2472 1.1 jdolecek i++; 2473 1.1 jdolecek } 2474 1.1 jdolecek } 2475 1.1 jdolecek } 2476 1.99 msaitoh } 2477 1.99 msaitoh 2478 1.102 maxv static void 2479 1.99 msaitoh sk_init_xmac(struct sk_if_softc *sc_if) 2480 1.99 msaitoh { 2481 1.99 msaitoh struct sk_softc *sc = sc_if->sk_softc; 2482 1.99 msaitoh struct ifnet *ifp = &sc_if->sk_ethercom.ec_if; 2483 1.99 msaitoh 2484 1.99 msaitoh sk_unreset_xmac(sc_if); 2485 1.1 jdolecek 2486 1.1 jdolecek /* Set station address */ 2487 1.1 jdolecek SK_XM_WRITE_2(sc_if, XM_PAR0, 2488 1.91 msaitoh *(uint16_t *)(&sc_if->sk_enaddr[0])); 2489 1.1 jdolecek SK_XM_WRITE_2(sc_if, XM_PAR1, 2490 1.91 msaitoh *(uint16_t *)(&sc_if->sk_enaddr[2])); 2491 1.1 jdolecek SK_XM_WRITE_2(sc_if, XM_PAR2, 2492 1.91 msaitoh *(uint16_t *)(&sc_if->sk_enaddr[4])); 2493 1.1 jdolecek SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_USE_STATION); 2494 1.1 jdolecek 2495 1.31 riz if (ifp->if_flags & IFF_PROMISC) 2496 1.1 jdolecek SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_PROMISC); 2497 1.31 riz else 2498 1.1 jdolecek SK_XM_CLRBIT_4(sc_if, XM_MODE, XM_MODE_RX_PROMISC); 2499 1.1 jdolecek 2500 1.31 riz if (ifp->if_flags & IFF_BROADCAST) 2501 1.1 jdolecek SK_XM_CLRBIT_4(sc_if, XM_MODE, XM_MODE_RX_NOBROAD); 2502 1.31 riz else 2503 1.1 jdolecek SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_NOBROAD); 2504 1.1 jdolecek 2505 1.1 jdolecek /* We don't need the FCS appended to the packet. */ 2506 1.1 jdolecek SK_XM_SETBIT_2(sc_if, XM_RXCMD, XM_RXCMD_STRIPFCS); 2507 1.1 jdolecek 2508 1.1 jdolecek /* We want short frames padded to 60 bytes. */ 2509 1.1 jdolecek SK_XM_SETBIT_2(sc_if, XM_TXCMD, XM_TXCMD_AUTOPAD); 2510 1.1 jdolecek 2511 1.1 jdolecek /* 2512 1.103 msaitoh * Enable the reception of all error frames. This is 2513 1.1 jdolecek * a necessary evil due to the design of the XMAC. The 2514 1.1 jdolecek * XMAC's receive FIFO is only 8K in size, however jumbo 2515 1.1 jdolecek * frames can be up to 9000 bytes in length. When bad 2516 1.1 jdolecek * frame filtering is enabled, the XMAC's RX FIFO operates 2517 1.1 jdolecek * in 'store and forward' mode. For this to work, the 2518 1.1 jdolecek * entire frame has to fit into the FIFO, but that means 2519 1.1 jdolecek * that jumbo frames larger than 8192 bytes will be 2520 1.1 jdolecek * truncated. Disabling all bad frame filtering causes 2521 1.1 jdolecek * the RX FIFO to operate in streaming mode, in which 2522 1.110 andvar * case the XMAC will start transferring frames out of the 2523 1.1 jdolecek * RX FIFO as soon as the FIFO threshold is reached. 2524 1.1 jdolecek */ 2525 1.96 msaitoh SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_BADFRAMES | 2526 1.96 msaitoh XM_MODE_RX_GIANTS | XM_MODE_RX_RUNTS | XM_MODE_RX_CRCERRS | 2527 1.1 jdolecek XM_MODE_RX_INRANGELEN); 2528 1.1 jdolecek 2529 1.1 jdolecek if (ifp->if_mtu > (ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN)) 2530 1.1 jdolecek SK_XM_SETBIT_2(sc_if, XM_RXCMD, XM_RXCMD_BIGPKTOK); 2531 1.1 jdolecek else 2532 1.1 jdolecek SK_XM_CLRBIT_2(sc_if, XM_RXCMD, XM_RXCMD_BIGPKTOK); 2533 1.1 jdolecek 2534 1.1 jdolecek /* 2535 1.1 jdolecek * Bump up the transmit threshold. This helps hold off transmit 2536 1.1 jdolecek * underruns when we're blasting traffic from both ports at once. 2537 1.1 jdolecek */ 2538 1.1 jdolecek SK_XM_WRITE_2(sc_if, XM_TX_REQTHRESH, SK_XM_TX_FIFOTHRESH); 2539 1.1 jdolecek 2540 1.1 jdolecek /* Set multicast filter */ 2541 1.1 jdolecek sk_setmulti(sc_if); 2542 1.1 jdolecek 2543 1.1 jdolecek /* Clear and enable interrupts */ 2544 1.1 jdolecek SK_XM_READ_2(sc_if, XM_ISR); 2545 1.1 jdolecek if (sc_if->sk_phytype == SK_PHYTYPE_XMAC) 2546 1.1 jdolecek SK_XM_WRITE_2(sc_if, XM_IMR, XM_INTRS); 2547 1.1 jdolecek else 2548 1.1 jdolecek SK_XM_WRITE_2(sc_if, XM_IMR, 0xFFFF); 2549 1.1 jdolecek 2550 1.1 jdolecek /* Configure MAC arbiter */ 2551 1.31 riz switch (sc_if->sk_xmac_rev) { 2552 1.1 jdolecek case XM_XMAC_REV_B2: 2553 1.1 jdolecek sk_win_write_1(sc, SK_RCINIT_RX1, SK_RCINIT_XMAC_B2); 2554 1.1 jdolecek sk_win_write_1(sc, SK_RCINIT_TX1, SK_RCINIT_XMAC_B2); 2555 1.1 jdolecek sk_win_write_1(sc, SK_RCINIT_RX2, SK_RCINIT_XMAC_B2); 2556 1.1 jdolecek sk_win_write_1(sc, SK_RCINIT_TX2, SK_RCINIT_XMAC_B2); 2557 1.1 jdolecek sk_win_write_1(sc, SK_MINIT_RX1, SK_MINIT_XMAC_B2); 2558 1.1 jdolecek sk_win_write_1(sc, SK_MINIT_TX1, SK_MINIT_XMAC_B2); 2559 1.1 jdolecek sk_win_write_1(sc, SK_MINIT_RX2, SK_MINIT_XMAC_B2); 2560 1.1 jdolecek sk_win_write_1(sc, SK_MINIT_TX2, SK_MINIT_XMAC_B2); 2561 1.1 jdolecek sk_win_write_1(sc, SK_RECOVERY_CTL, SK_RECOVERY_XMAC_B2); 2562 1.1 jdolecek break; 2563 1.1 jdolecek case XM_XMAC_REV_C1: 2564 1.1 jdolecek sk_win_write_1(sc, SK_RCINIT_RX1, SK_RCINIT_XMAC_C1); 2565 1.1 jdolecek sk_win_write_1(sc, SK_RCINIT_TX1, SK_RCINIT_XMAC_C1); 2566 1.1 jdolecek sk_win_write_1(sc, SK_RCINIT_RX2, SK_RCINIT_XMAC_C1); 2567 1.1 jdolecek sk_win_write_1(sc, SK_RCINIT_TX2, SK_RCINIT_XMAC_C1); 2568 1.1 jdolecek sk_win_write_1(sc, SK_MINIT_RX1, SK_MINIT_XMAC_C1); 2569 1.1 jdolecek sk_win_write_1(sc, SK_MINIT_TX1, SK_MINIT_XMAC_C1); 2570 1.1 jdolecek sk_win_write_1(sc, SK_MINIT_RX2, SK_MINIT_XMAC_C1); 2571 1.1 jdolecek sk_win_write_1(sc, SK_MINIT_TX2, SK_MINIT_XMAC_C1); 2572 1.1 jdolecek sk_win_write_1(sc, SK_RECOVERY_CTL, SK_RECOVERY_XMAC_B2); 2573 1.1 jdolecek break; 2574 1.1 jdolecek default: 2575 1.1 jdolecek break; 2576 1.1 jdolecek } 2577 1.1 jdolecek sk_win_write_2(sc, SK_MACARB_CTL, 2578 1.96 msaitoh SK_MACARBCTL_UNRESET | SK_MACARBCTL_FASTOE_OFF); 2579 1.1 jdolecek 2580 1.1 jdolecek sc_if->sk_link = 1; 2581 1.1 jdolecek } 2582 1.1 jdolecek 2583 1.102 maxv static void 2584 1.99 msaitoh sk_unreset_yukon(struct sk_if_softc *sc_if) 2585 1.1 jdolecek { 2586 1.91 msaitoh uint32_t /*mac, */phy; 2587 1.16 xtraeme struct sk_softc *sc; 2588 1.1 jdolecek 2589 1.99 msaitoh DPRINTFN(1, ("sk_unreset_yukon: start: sk_csr=%#x\n", 2590 1.1 jdolecek CSR_READ_4(sc_if->sk_softc, SK_CSR))); 2591 1.1 jdolecek 2592 1.16 xtraeme sc = sc_if->sk_softc; 2593 1.16 xtraeme if (sc->sk_type == SK_YUKON_LITE && 2594 1.16 xtraeme sc->sk_rev >= SK_YUKON_LITE_REV_A3) { 2595 1.16 xtraeme /* Take PHY out of reset. */ 2596 1.16 xtraeme sk_win_write_4(sc, SK_GPIO, 2597 1.100 msaitoh (sk_win_read_4(sc, SK_GPIO) | SK_GPIO_DIR9) 2598 1.100 msaitoh & ~SK_GPIO_DAT9); 2599 1.16 xtraeme } 2600 1.16 xtraeme 2601 1.1 jdolecek /* GMAC and GPHY Reset */ 2602 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, SK_GPHY_RESET_SET); 2603 1.1 jdolecek 2604 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: 1\n")); 2605 1.1 jdolecek 2606 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_RESET_SET); 2607 1.1 jdolecek DELAY(1000); 2608 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_RESET_CLEAR); 2609 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_RESET_SET); 2610 1.1 jdolecek DELAY(1000); 2611 1.1 jdolecek 2612 1.1 jdolecek 2613 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: 2\n")); 2614 1.1 jdolecek 2615 1.1 jdolecek phy = SK_GPHY_INT_POL_HI | SK_GPHY_DIS_FC | SK_GPHY_DIS_SLEEP | 2616 1.1 jdolecek SK_GPHY_ENA_XC | SK_GPHY_ANEG_ALL | SK_GPHY_ENA_PAUSE; 2617 1.1 jdolecek 2618 1.31 riz switch (sc_if->sk_softc->sk_pmd) { 2619 1.1 jdolecek case IFM_1000_SX: 2620 1.1 jdolecek case IFM_1000_LX: 2621 1.1 jdolecek phy |= SK_GPHY_FIBER; 2622 1.1 jdolecek break; 2623 1.1 jdolecek 2624 1.1 jdolecek case IFM_1000_CX: 2625 1.1 jdolecek case IFM_1000_T: 2626 1.1 jdolecek phy |= SK_GPHY_COPPER; 2627 1.1 jdolecek break; 2628 1.1 jdolecek } 2629 1.1 jdolecek 2630 1.1 jdolecek DPRINTFN(3, ("sk_init_yukon: phy=%#x\n", phy)); 2631 1.1 jdolecek 2632 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, phy | SK_GPHY_RESET_SET); 2633 1.1 jdolecek DELAY(1000); 2634 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, phy | SK_GPHY_RESET_CLEAR); 2635 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_LOOP_OFF | 2636 1.1 jdolecek SK_GMAC_PAUSE_ON | SK_GMAC_RESET_CLEAR); 2637 1.1 jdolecek 2638 1.1 jdolecek DPRINTFN(3, ("sk_init_yukon: gmac_ctrl=%#x\n", 2639 1.1 jdolecek SK_IF_READ_4(sc_if, 0, SK_GMAC_CTRL))); 2640 1.99 msaitoh } 2641 1.99 msaitoh 2642 1.102 maxv static void 2643 1.99 msaitoh sk_init_yukon(struct sk_if_softc *sc_if) 2644 1.99 msaitoh { 2645 1.99 msaitoh uint16_t reg; 2646 1.99 msaitoh int i; 2647 1.1 jdolecek 2648 1.99 msaitoh DPRINTFN(1, ("sk_init_yukon: start\n")); 2649 1.99 msaitoh sk_unreset_yukon(sc_if); 2650 1.1 jdolecek 2651 1.1 jdolecek /* unused read of the interrupt source register */ 2652 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: 4\n")); 2653 1.1 jdolecek SK_IF_READ_2(sc_if, 0, SK_GMAC_ISR); 2654 1.1 jdolecek 2655 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: 4a\n")); 2656 1.1 jdolecek reg = SK_YU_READ_2(sc_if, YUKON_PAR); 2657 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: YUKON_PAR=%#x\n", reg)); 2658 1.1 jdolecek 2659 1.1 jdolecek /* MIB Counter Clear Mode set */ 2660 1.92 msaitoh reg |= YU_PAR_MIB_CLR; 2661 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: YUKON_PAR=%#x\n", reg)); 2662 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: 4b\n")); 2663 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_PAR, reg); 2664 1.14 perry 2665 1.1 jdolecek /* MIB Counter Clear Mode clear */ 2666 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: 5\n")); 2667 1.92 msaitoh reg &= ~YU_PAR_MIB_CLR; 2668 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_PAR, reg); 2669 1.1 jdolecek 2670 1.1 jdolecek /* receive control reg */ 2671 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: 7\n")); 2672 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_RCR, YU_RCR_UFLEN | YU_RCR_MUFLEN | 2673 1.1 jdolecek YU_RCR_CRCR); 2674 1.1 jdolecek 2675 1.1 jdolecek /* transmit parameter register */ 2676 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: 8\n")); 2677 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_TPR, YU_TPR_JAM_LEN(0x3) | 2678 1.100 msaitoh YU_TPR_JAM_IPG(0xb) | YU_TPR_JAM2DATA_IPG(0x1a)); 2679 1.1 jdolecek 2680 1.1 jdolecek /* serial mode register */ 2681 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: 9\n")); 2682 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_SMR, YU_SMR_DATA_BLIND(0x1c) | 2683 1.22 riz YU_SMR_MFL_VLAN | YU_SMR_MFL_JUMBO | 2684 1.22 riz YU_SMR_IPG_DATA(0x1e)); 2685 1.1 jdolecek 2686 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: 10\n")); 2687 1.1 jdolecek /* Setup Yukon's address */ 2688 1.1 jdolecek for (i = 0; i < 3; i++) { 2689 1.1 jdolecek /* Write Source Address 1 (unicast filter) */ 2690 1.14 perry SK_YU_WRITE_2(sc_if, YUKON_SAL1 + i * 4, 2691 1.1 jdolecek sc_if->sk_enaddr[i * 2] | 2692 1.1 jdolecek sc_if->sk_enaddr[i * 2 + 1] << 8); 2693 1.1 jdolecek } 2694 1.1 jdolecek 2695 1.1 jdolecek for (i = 0; i < 3; i++) { 2696 1.1 jdolecek reg = sk_win_read_2(sc_if->sk_softc, 2697 1.1 jdolecek SK_MAC1_0 + i * 2 + sc_if->sk_port * 8); 2698 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_SAL2 + i * 4, reg); 2699 1.1 jdolecek } 2700 1.1 jdolecek 2701 1.9 kleink /* Set multicast filter */ 2702 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: 11\n")); 2703 1.9 kleink sk_setmulti(sc_if); 2704 1.1 jdolecek 2705 1.1 jdolecek /* enable interrupt mask for counter overflows */ 2706 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: 12\n")); 2707 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_TIMR, 0); 2708 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_RIMR, 0); 2709 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_TRIMR, 0); 2710 1.1 jdolecek 2711 1.1 jdolecek /* Configure RX MAC FIFO */ 2712 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_CLEAR); 2713 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXMF1_CTRL_TEST, SK_RFCTL_OPERATION_ON); 2714 1.14 perry 2715 1.1 jdolecek /* Configure TX MAC FIFO */ 2716 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_CLEAR); 2717 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_TXMF1_CTRL_TEST, SK_TFCTL_OPERATION_ON); 2718 1.14 perry 2719 1.1 jdolecek DPRINTFN(6, ("sk_init_yukon: end\n")); 2720 1.1 jdolecek } 2721 1.1 jdolecek 2722 1.1 jdolecek /* 2723 1.1 jdolecek * Note that to properly initialize any part of the GEnesis chip, 2724 1.1 jdolecek * you first have to take it out of reset mode. 2725 1.1 jdolecek */ 2726 1.102 maxv static int 2727 1.1 jdolecek sk_init(struct ifnet *ifp) 2728 1.1 jdolecek { 2729 1.1 jdolecek struct sk_if_softc *sc_if = ifp->if_softc; 2730 1.1 jdolecek struct sk_softc *sc = sc_if->sk_softc; 2731 1.1 jdolecek struct mii_data *mii = &sc_if->sk_mii; 2732 1.46 dyoung int rc = 0, s; 2733 1.91 msaitoh uint32_t imr, imtimer_ticks; 2734 1.1 jdolecek 2735 1.1 jdolecek DPRINTFN(1, ("sk_init\n")); 2736 1.1 jdolecek 2737 1.1 jdolecek s = splnet(); 2738 1.1 jdolecek 2739 1.16 xtraeme if (ifp->if_flags & IFF_RUNNING) { 2740 1.16 xtraeme splx(s); 2741 1.16 xtraeme return 0; 2742 1.16 xtraeme } 2743 1.16 xtraeme 2744 1.1 jdolecek /* Cancel pending I/O and free all RX/TX buffers. */ 2745 1.96 msaitoh sk_stop(ifp, 0); 2746 1.1 jdolecek 2747 1.1 jdolecek if (sc->sk_type == SK_GENESIS) { 2748 1.1 jdolecek /* Configure LINK_SYNC LED */ 2749 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_ON); 2750 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, 2751 1.1 jdolecek SK_LINKLED_LINKSYNC_ON); 2752 1.1 jdolecek 2753 1.1 jdolecek /* Configure RX LED */ 2754 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL, 2755 1.1 jdolecek SK_RXLEDCTL_COUNTER_START); 2756 1.14 perry 2757 1.1 jdolecek /* Configure TX LED */ 2758 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL, 2759 1.1 jdolecek SK_TXLEDCTL_COUNTER_START); 2760 1.1 jdolecek } 2761 1.1 jdolecek 2762 1.1 jdolecek /* Configure I2C registers */ 2763 1.1 jdolecek 2764 1.1 jdolecek /* Configure XMAC(s) */ 2765 1.1 jdolecek switch (sc->sk_type) { 2766 1.1 jdolecek case SK_GENESIS: 2767 1.1 jdolecek sk_init_xmac(sc_if); 2768 1.1 jdolecek break; 2769 1.1 jdolecek case SK_YUKON: 2770 1.11 skd case SK_YUKON_LITE: 2771 1.11 skd case SK_YUKON_LP: 2772 1.1 jdolecek sk_init_yukon(sc_if); 2773 1.1 jdolecek break; 2774 1.1 jdolecek } 2775 1.46 dyoung if ((rc = mii_mediachg(mii)) == ENXIO) 2776 1.46 dyoung rc = 0; 2777 1.46 dyoung else if (rc != 0) 2778 1.46 dyoung goto out; 2779 1.1 jdolecek 2780 1.1 jdolecek if (sc->sk_type == SK_GENESIS) { 2781 1.1 jdolecek /* Configure MAC FIFOs */ 2782 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_UNRESET); 2783 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXF1_END, SK_FIFO_END); 2784 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_ON); 2785 1.14 perry 2786 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_UNRESET); 2787 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_TXF1_END, SK_FIFO_END); 2788 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_ON); 2789 1.1 jdolecek } 2790 1.1 jdolecek 2791 1.1 jdolecek /* Configure transmit arbiter(s) */ 2792 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL, 2793 1.96 msaitoh SK_TXARCTL_ON | SK_TXARCTL_FSYNC_ON); 2794 1.1 jdolecek 2795 1.1 jdolecek /* Configure RAMbuffers */ 2796 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_UNRESET); 2797 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_START, sc_if->sk_rx_ramstart); 2798 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_WR_PTR, sc_if->sk_rx_ramstart); 2799 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_RD_PTR, sc_if->sk_rx_ramstart); 2800 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_END, sc_if->sk_rx_ramend); 2801 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_ON); 2802 1.1 jdolecek 2803 1.1 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_UNRESET); 2804 1.1 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_STORENFWD_ON); 2805 1.1 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_START, sc_if->sk_tx_ramstart); 2806 1.1 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_WR_PTR, sc_if->sk_tx_ramstart); 2807 1.1 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_RD_PTR, sc_if->sk_tx_ramstart); 2808 1.1 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_END, sc_if->sk_tx_ramend); 2809 1.1 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_ON); 2810 1.1 jdolecek 2811 1.1 jdolecek /* Configure BMUs */ 2812 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_ONLINE); 2813 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_CURADDR_LO, 2814 1.1 jdolecek SK_RX_RING_ADDR(sc_if, 0)); 2815 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_CURADDR_HI, 0); 2816 1.1 jdolecek 2817 1.1 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_BMU_CSR, SK_TXBMU_ONLINE); 2818 1.1 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_CURADDR_LO, 2819 1.92 msaitoh SK_TX_RING_ADDR(sc_if, 0)); 2820 1.1 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_CURADDR_HI, 0); 2821 1.1 jdolecek 2822 1.1 jdolecek /* Init descriptors */ 2823 1.1 jdolecek if (sk_init_rx_ring(sc_if) == ENOBUFS) { 2824 1.51 christos aprint_error_dev(sc_if->sk_dev, "initialization failed: no " 2825 1.48 cegger "memory for rx buffers\n"); 2826 1.96 msaitoh sk_stop(ifp, 0); 2827 1.1 jdolecek splx(s); 2828 1.31 riz return ENOBUFS; 2829 1.1 jdolecek } 2830 1.1 jdolecek 2831 1.1 jdolecek if (sk_init_tx_ring(sc_if) == ENOBUFS) { 2832 1.51 christos aprint_error_dev(sc_if->sk_dev, "initialization failed: no " 2833 1.48 cegger "memory for tx buffers\n"); 2834 1.96 msaitoh sk_stop(ifp, 0); 2835 1.1 jdolecek splx(s); 2836 1.31 riz return ENOBUFS; 2837 1.1 jdolecek } 2838 1.1 jdolecek 2839 1.20 riz /* Set interrupt moderation if changed via sysctl. */ 2840 1.20 riz switch (sc->sk_type) { 2841 1.20 riz case SK_GENESIS: 2842 1.36 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_GENESIS; 2843 1.20 riz break; 2844 1.20 riz case SK_YUKON_EC: 2845 1.36 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON_EC; 2846 1.20 riz break; 2847 1.20 riz default: 2848 1.36 msaitoh imtimer_ticks = SK_IMTIMER_TICKS_YUKON; 2849 1.20 riz } 2850 1.20 riz imr = sk_win_read_4(sc, SK_IMTIMERINIT); 2851 1.20 riz if (imr != SK_IM_USECS(sc->sk_int_mod)) { 2852 1.20 riz sk_win_write_4(sc, SK_IMTIMERINIT, 2853 1.20 riz SK_IM_USECS(sc->sk_int_mod)); 2854 1.51 christos aprint_verbose_dev(sc->sk_dev, 2855 1.51 christos "interrupt moderation is %d us\n", sc->sk_int_mod); 2856 1.20 riz } 2857 1.20 riz 2858 1.1 jdolecek /* Configure interrupt handling */ 2859 1.1 jdolecek CSR_READ_4(sc, SK_ISSR); 2860 1.1 jdolecek if (sc_if->sk_port == SK_PORT_A) 2861 1.1 jdolecek sc->sk_intrmask |= SK_INTRS1; 2862 1.1 jdolecek else 2863 1.1 jdolecek sc->sk_intrmask |= SK_INTRS2; 2864 1.1 jdolecek 2865 1.1 jdolecek sc->sk_intrmask |= SK_ISR_EXTERNAL_REG; 2866 1.1 jdolecek 2867 1.1 jdolecek CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask); 2868 1.1 jdolecek 2869 1.1 jdolecek /* Start BMUs. */ 2870 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_RX_START); 2871 1.1 jdolecek 2872 1.1 jdolecek if (sc->sk_type == SK_GENESIS) { 2873 1.1 jdolecek /* Enable XMACs TX and RX state machines */ 2874 1.1 jdolecek SK_XM_CLRBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_IGNPAUSE); 2875 1.1 jdolecek SK_XM_SETBIT_2(sc_if, XM_MMUCMD, 2876 1.96 msaitoh XM_MMUCMD_TX_ENB | XM_MMUCMD_RX_ENB); 2877 1.1 jdolecek } 2878 1.1 jdolecek 2879 1.11 skd if (SK_YUKON_FAMILY(sc->sk_type)) { 2880 1.91 msaitoh uint16_t reg = SK_YU_READ_2(sc_if, YUKON_GPCR); 2881 1.1 jdolecek reg |= YU_GPCR_TXEN | YU_GPCR_RXEN; 2882 1.36 msaitoh #if 0 2883 1.36 msaitoh /* XXX disable 100Mbps and full duplex mode? */ 2884 1.36 msaitoh reg &= ~(YU_GPCR_SPEED | YU_GPCR_DPLX_EN); 2885 1.36 msaitoh #endif 2886 1.1 jdolecek SK_YU_WRITE_2(sc_if, YUKON_GPCR, reg); 2887 1.1 jdolecek } 2888 1.1 jdolecek 2889 1.1 jdolecek 2890 1.1 jdolecek ifp->if_flags |= IFF_RUNNING; 2891 1.1 jdolecek ifp->if_flags &= ~IFF_OACTIVE; 2892 1.79 christos callout_reset(&sc_if->sk_tick_ch, hz, sk_tick, sc_if); 2893 1.1 jdolecek 2894 1.46 dyoung out: 2895 1.1 jdolecek splx(s); 2896 1.46 dyoung return rc; 2897 1.1 jdolecek } 2898 1.1 jdolecek 2899 1.102 maxv static void 2900 1.35 christos sk_stop(struct ifnet *ifp, int disable) 2901 1.1 jdolecek { 2902 1.92 msaitoh struct sk_if_softc *sc_if = ifp->if_softc; 2903 1.1 jdolecek struct sk_softc *sc = sc_if->sk_softc; 2904 1.1 jdolecek int i; 2905 1.1 jdolecek 2906 1.1 jdolecek DPRINTFN(1, ("sk_stop\n")); 2907 1.1 jdolecek 2908 1.1 jdolecek callout_stop(&sc_if->sk_tick_ch); 2909 1.1 jdolecek 2910 1.1 jdolecek if (sc_if->sk_phytype == SK_PHYTYPE_BCOM) { 2911 1.91 msaitoh uint32_t val; 2912 1.1 jdolecek 2913 1.1 jdolecek /* Put PHY back into reset. */ 2914 1.1 jdolecek val = sk_win_read_4(sc, SK_GPIO); 2915 1.1 jdolecek if (sc_if->sk_port == SK_PORT_A) { 2916 1.1 jdolecek val |= SK_GPIO_DIR0; 2917 1.1 jdolecek val &= ~SK_GPIO_DAT0; 2918 1.1 jdolecek } else { 2919 1.1 jdolecek val |= SK_GPIO_DIR2; 2920 1.1 jdolecek val &= ~SK_GPIO_DAT2; 2921 1.1 jdolecek } 2922 1.1 jdolecek sk_win_write_4(sc, SK_GPIO, val); 2923 1.1 jdolecek } 2924 1.1 jdolecek 2925 1.1 jdolecek /* Turn off various components of this interface. */ 2926 1.1 jdolecek SK_XM_SETBIT_2(sc_if, XM_GPIO, XM_GPIO_RESETMAC); 2927 1.1 jdolecek switch (sc->sk_type) { 2928 1.1 jdolecek case SK_GENESIS: 2929 1.1 jdolecek SK_IF_WRITE_2(sc_if, 0, SK_TXF1_MACCTL, 2930 1.1 jdolecek SK_TXMACCTL_XMAC_RESET); 2931 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_RESET); 2932 1.1 jdolecek break; 2933 1.1 jdolecek case SK_YUKON: 2934 1.11 skd case SK_YUKON_LITE: 2935 1.11 skd case SK_YUKON_LP: 2936 1.1 jdolecek SK_IF_WRITE_1(sc_if,0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_SET); 2937 1.1 jdolecek SK_IF_WRITE_1(sc_if,0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_SET); 2938 1.1 jdolecek break; 2939 1.1 jdolecek } 2940 1.1 jdolecek SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_OFFLINE); 2941 1.96 msaitoh SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_RESET |SK_RBCTL_OFF); 2942 1.1 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_BMU_CSR, SK_TXBMU_OFFLINE); 2943 1.1 jdolecek SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_RESET|SK_RBCTL_OFF); 2944 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL, SK_TXARCTL_OFF); 2945 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL, SK_RXLEDCTL_COUNTER_STOP); 2946 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL, SK_RXLEDCTL_COUNTER_STOP); 2947 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_OFF); 2948 1.1 jdolecek SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_LINKSYNC_OFF); 2949 1.1 jdolecek 2950 1.1 jdolecek /* Disable interrupts */ 2951 1.1 jdolecek if (sc_if->sk_port == SK_PORT_A) 2952 1.1 jdolecek sc->sk_intrmask &= ~SK_INTRS1; 2953 1.1 jdolecek else 2954 1.1 jdolecek sc->sk_intrmask &= ~SK_INTRS2; 2955 1.1 jdolecek CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask); 2956 1.1 jdolecek 2957 1.1 jdolecek SK_XM_READ_2(sc_if, XM_ISR); 2958 1.1 jdolecek SK_XM_WRITE_2(sc_if, XM_IMR, 0xFFFF); 2959 1.1 jdolecek 2960 1.1 jdolecek /* Free RX and TX mbufs still in the queues. */ 2961 1.1 jdolecek for (i = 0; i < SK_RX_RING_CNT; i++) { 2962 1.113 rin m_freem(sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf); 2963 1.113 rin sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf = NULL; 2964 1.1 jdolecek } 2965 1.1 jdolecek 2966 1.1 jdolecek for (i = 0; i < SK_TX_RING_CNT; i++) { 2967 1.113 rin m_freem(sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf); 2968 1.113 rin sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf = NULL; 2969 1.1 jdolecek } 2970 1.1 jdolecek 2971 1.96 msaitoh ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 2972 1.1 jdolecek } 2973 1.1 jdolecek 2974 1.60 kefren /* Power Management Framework */ 2975 1.60 kefren 2976 1.60 kefren static bool 2977 1.65 dyoung skc_suspend(device_t dv, const pmf_qual_t *qual) 2978 1.60 kefren { 2979 1.60 kefren struct sk_softc *sc = device_private(dv); 2980 1.60 kefren 2981 1.60 kefren DPRINTFN(2, ("skc_suspend\n")); 2982 1.60 kefren 2983 1.60 kefren /* Turn off the driver is loaded LED */ 2984 1.60 kefren CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_OFF); 2985 1.60 kefren 2986 1.60 kefren return true; 2987 1.60 kefren } 2988 1.60 kefren 2989 1.60 kefren static bool 2990 1.65 dyoung skc_resume(device_t dv, const pmf_qual_t *qual) 2991 1.60 kefren { 2992 1.60 kefren struct sk_softc *sc = device_private(dv); 2993 1.60 kefren 2994 1.60 kefren DPRINTFN(2, ("skc_resume\n")); 2995 1.60 kefren 2996 1.60 kefren sk_reset(sc); 2997 1.60 kefren CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_ON); 2998 1.60 kefren 2999 1.60 kefren return true; 3000 1.60 kefren } 3001 1.60 kefren 3002 1.60 kefren static bool 3003 1.65 dyoung sk_resume(device_t dv, const pmf_qual_t *qual) 3004 1.60 kefren { 3005 1.60 kefren struct sk_if_softc *sc_if = device_private(dv); 3006 1.60 kefren 3007 1.60 kefren sk_init_yukon(sc_if); 3008 1.60 kefren return true; 3009 1.60 kefren } 3010 1.60 kefren 3011 1.51 christos CFATTACH_DECL_NEW(skc, sizeof(struct sk_softc), 3012 1.51 christos skc_probe, skc_attach, NULL, NULL); 3013 1.1 jdolecek 3014 1.51 christos CFATTACH_DECL_NEW(sk, sizeof(struct sk_if_softc), 3015 1.51 christos sk_probe, sk_attach, NULL, NULL); 3016 1.1 jdolecek 3017 1.1 jdolecek #ifdef SK_DEBUG 3018 1.102 maxv static void 3019 1.1 jdolecek sk_dump_txdesc(struct sk_tx_desc *desc, int idx) 3020 1.1 jdolecek { 3021 1.1 jdolecek #define DESC_PRINT(X) \ 3022 1.100 msaitoh if (X) \ 3023 1.1 jdolecek printf("txdesc[%d]." #X "=%#x\n", \ 3024 1.29 riz idx, X); 3025 1.1 jdolecek 3026 1.29 riz DESC_PRINT(le32toh(desc->sk_ctl)); 3027 1.29 riz DESC_PRINT(le32toh(desc->sk_next)); 3028 1.29 riz DESC_PRINT(le32toh(desc->sk_data_lo)); 3029 1.29 riz DESC_PRINT(le32toh(desc->sk_data_hi)); 3030 1.29 riz DESC_PRINT(le32toh(desc->sk_xmac_txstat)); 3031 1.29 riz DESC_PRINT(le16toh(desc->sk_rsvd0)); 3032 1.29 riz DESC_PRINT(le16toh(desc->sk_csum_startval)); 3033 1.29 riz DESC_PRINT(le16toh(desc->sk_csum_startpos)); 3034 1.29 riz DESC_PRINT(le16toh(desc->sk_csum_writepos)); 3035 1.29 riz DESC_PRINT(le16toh(desc->sk_rsvd1)); 3036 1.1 jdolecek #undef PRINT 3037 1.1 jdolecek } 3038 1.1 jdolecek 3039 1.102 maxv static void 3040 1.1 jdolecek sk_dump_bytes(const char *data, int len) 3041 1.1 jdolecek { 3042 1.1 jdolecek int c, i, j; 3043 1.1 jdolecek 3044 1.1 jdolecek for (i = 0; i < len; i += 16) { 3045 1.1 jdolecek printf("%08x ", i); 3046 1.1 jdolecek c = len - i; 3047 1.1 jdolecek if (c > 16) c = 16; 3048 1.1 jdolecek 3049 1.1 jdolecek for (j = 0; j < c; j++) { 3050 1.1 jdolecek printf("%02x ", data[i + j] & 0xff); 3051 1.1 jdolecek if ((j & 0xf) == 7 && j > 0) 3052 1.1 jdolecek printf(" "); 3053 1.1 jdolecek } 3054 1.14 perry 3055 1.1 jdolecek for (; j < 16; j++) 3056 1.1 jdolecek printf(" "); 3057 1.1 jdolecek printf(" "); 3058 1.1 jdolecek 3059 1.1 jdolecek for (j = 0; j < c; j++) { 3060 1.1 jdolecek int ch = data[i + j] & 0xff; 3061 1.1 jdolecek printf("%c", ' ' <= ch && ch <= '~' ? ch : ' '); 3062 1.1 jdolecek } 3063 1.14 perry 3064 1.1 jdolecek printf("\n"); 3065 1.14 perry 3066 1.1 jdolecek if (c < 16) 3067 1.1 jdolecek break; 3068 1.1 jdolecek } 3069 1.1 jdolecek } 3070 1.1 jdolecek 3071 1.102 maxv static void 3072 1.1 jdolecek sk_dump_mbuf(struct mbuf *m) 3073 1.1 jdolecek { 3074 1.1 jdolecek int count = m->m_pkthdr.len; 3075 1.1 jdolecek 3076 1.1 jdolecek printf("m=%p, m->m_pkthdr.len=%d\n", m, m->m_pkthdr.len); 3077 1.1 jdolecek 3078 1.1 jdolecek while (count > 0 && m) { 3079 1.1 jdolecek printf("m=%p, m->m_data=%p, m->m_len=%d\n", 3080 1.1 jdolecek m, m->m_data, m->m_len); 3081 1.1 jdolecek sk_dump_bytes(mtod(m, char *), m->m_len); 3082 1.1 jdolecek 3083 1.1 jdolecek count -= m->m_len; 3084 1.1 jdolecek m = m->m_next; 3085 1.1 jdolecek } 3086 1.1 jdolecek } 3087 1.1 jdolecek #endif 3088 1.20 riz 3089 1.20 riz static int 3090 1.20 riz sk_sysctl_handler(SYSCTLFN_ARGS) 3091 1.20 riz { 3092 1.20 riz int error, t; 3093 1.20 riz struct sysctlnode node; 3094 1.20 riz struct sk_softc *sc; 3095 1.20 riz 3096 1.20 riz node = *rnode; 3097 1.20 riz sc = node.sysctl_data; 3098 1.20 riz t = sc->sk_int_mod; 3099 1.20 riz node.sysctl_data = &t; 3100 1.20 riz error = sysctl_lookup(SYSCTLFN_CALL(&node)); 3101 1.20 riz if (error || newp == NULL) 3102 1.31 riz return error; 3103 1.20 riz 3104 1.20 riz if (t < SK_IM_MIN || t > SK_IM_MAX) 3105 1.31 riz return EINVAL; 3106 1.20 riz 3107 1.20 riz /* update the softc with sysctl-changed value, and mark 3108 1.20 riz for hardware update */ 3109 1.20 riz sc->sk_int_mod = t; 3110 1.20 riz sc->sk_int_mod_pending = 1; 3111 1.31 riz return 0; 3112 1.20 riz } 3113 1.20 riz 3114 1.20 riz /* 3115 1.20 riz * Set up sysctl(3) MIB, hw.sk.* - Individual controllers will be 3116 1.20 riz * set up in skc_attach() 3117 1.20 riz */ 3118 1.20 riz SYSCTL_SETUP(sysctl_sk, "sysctl sk subtree setup") 3119 1.20 riz { 3120 1.20 riz int rc; 3121 1.20 riz const struct sysctlnode *node; 3122 1.20 riz 3123 1.20 riz if ((rc = sysctl_createv(clog, 0, NULL, &node, 3124 1.20 riz 0, CTLTYPE_NODE, "sk", 3125 1.20 riz SYSCTL_DESCR("sk interface controls"), 3126 1.20 riz NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) { 3127 1.20 riz goto err; 3128 1.20 riz } 3129 1.20 riz 3130 1.20 riz sk_root_num = node->sysctl_num; 3131 1.20 riz return; 3132 1.20 riz 3133 1.20 riz err: 3134 1.31 riz aprint_error("%s: syctl_createv failed (rc = %d)\n", __func__, rc); 3135 1.20 riz } 3136