12d586421SSepherosa Ziehau /****************************************************************************** 22d586421SSepherosa Ziehau * 32d586421SSepherosa Ziehau * Name : sky2.c 42d586421SSepherosa Ziehau * Project: Gigabit Ethernet Driver for FreeBSD 5.x/6.x 52d586421SSepherosa Ziehau * Version: $Revision: 1.23 $ 62d586421SSepherosa Ziehau * Date : $Date: 2005/12/22 09:04:11 $ 72d586421SSepherosa Ziehau * Purpose: Main driver source file 82d586421SSepherosa Ziehau * 92d586421SSepherosa Ziehau *****************************************************************************/ 102d586421SSepherosa Ziehau 112d586421SSepherosa Ziehau /****************************************************************************** 122d586421SSepherosa Ziehau * 132d586421SSepherosa Ziehau * LICENSE: 142d586421SSepherosa Ziehau * Copyright (C) Marvell International Ltd. and/or its affiliates 152d586421SSepherosa Ziehau * 162d586421SSepherosa Ziehau * The computer program files contained in this folder ("Files") 172d586421SSepherosa Ziehau * are provided to you under the BSD-type license terms provided 182d586421SSepherosa Ziehau * below, and any use of such Files and any derivative works 192d586421SSepherosa Ziehau * thereof created by you shall be governed by the following terms 202d586421SSepherosa Ziehau * and conditions: 212d586421SSepherosa Ziehau * 222d586421SSepherosa Ziehau * - Redistributions of source code must retain the above copyright 232d586421SSepherosa Ziehau * notice, this list of conditions and the following disclaimer. 242d586421SSepherosa Ziehau * - Redistributions in binary form must reproduce the above 252d586421SSepherosa Ziehau * copyright notice, this list of conditions and the following 262d586421SSepherosa Ziehau * disclaimer in the documentation and/or other materials provided 272d586421SSepherosa Ziehau * with the distribution. 282d586421SSepherosa Ziehau * - Neither the name of Marvell nor the names of its contributors 292d586421SSepherosa Ziehau * may be used to endorse or promote products derived from this 302d586421SSepherosa Ziehau * software without specific prior written permission. 312d586421SSepherosa Ziehau * 322d586421SSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 332d586421SSepherosa Ziehau * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 342d586421SSepherosa Ziehau * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 352d586421SSepherosa Ziehau * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 362d586421SSepherosa Ziehau * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 372d586421SSepherosa Ziehau * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 382d586421SSepherosa Ziehau * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 392d586421SSepherosa Ziehau * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 402d586421SSepherosa Ziehau * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 412d586421SSepherosa Ziehau * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 422d586421SSepherosa Ziehau * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 432d586421SSepherosa Ziehau * OF THE POSSIBILITY OF SUCH DAMAGE. 442d586421SSepherosa Ziehau * /LICENSE 452d586421SSepherosa Ziehau * 462d586421SSepherosa Ziehau *****************************************************************************/ 472d586421SSepherosa Ziehau 482d586421SSepherosa Ziehau /*- 492d586421SSepherosa Ziehau * Copyright (c) 1997, 1998, 1999, 2000 502d586421SSepherosa Ziehau * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 512d586421SSepherosa Ziehau * 522d586421SSepherosa Ziehau * Redistribution and use in source and binary forms, with or without 532d586421SSepherosa Ziehau * modification, are permitted provided that the following conditions 542d586421SSepherosa Ziehau * are met: 552d586421SSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright 562d586421SSepherosa Ziehau * notice, this list of conditions and the following disclaimer. 572d586421SSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright 582d586421SSepherosa Ziehau * notice, this list of conditions and the following disclaimer in the 592d586421SSepherosa Ziehau * documentation and/or other materials provided with the distribution. 602d586421SSepherosa Ziehau * 3. All advertising materials mentioning features or use of this software 612d586421SSepherosa Ziehau * must display the following acknowledgement: 622d586421SSepherosa Ziehau * This product includes software developed by Bill Paul. 632d586421SSepherosa Ziehau * 4. Neither the name of the author nor the names of any co-contributors 642d586421SSepherosa Ziehau * may be used to endorse or promote products derived from this software 652d586421SSepherosa Ziehau * without specific prior written permission. 662d586421SSepherosa Ziehau * 672d586421SSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 682d586421SSepherosa Ziehau * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 692d586421SSepherosa Ziehau * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 702d586421SSepherosa Ziehau * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 712d586421SSepherosa Ziehau * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 722d586421SSepherosa Ziehau * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 732d586421SSepherosa Ziehau * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 742d586421SSepherosa Ziehau * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 752d586421SSepherosa Ziehau * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 762d586421SSepherosa Ziehau * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 772d586421SSepherosa Ziehau * THE POSSIBILITY OF SUCH DAMAGE. 782d586421SSepherosa Ziehau */ 792d586421SSepherosa Ziehau /*- 802d586421SSepherosa Ziehau * Copyright (c) 2003 Nathan L. Binkert <binkertn@umich.edu> 812d586421SSepherosa Ziehau * 822d586421SSepherosa Ziehau * Permission to use, copy, modify, and distribute this software for any 832d586421SSepherosa Ziehau * purpose with or without fee is hereby granted, provided that the above 842d586421SSepherosa Ziehau * copyright notice and this permission notice appear in all copies. 852d586421SSepherosa Ziehau * 862d586421SSepherosa Ziehau * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 872d586421SSepherosa Ziehau * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 882d586421SSepherosa Ziehau * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 892d586421SSepherosa Ziehau * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 902d586421SSepherosa Ziehau * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 912d586421SSepherosa Ziehau * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 922d586421SSepherosa Ziehau * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 932d586421SSepherosa Ziehau */ 942d586421SSepherosa Ziehau 952d586421SSepherosa Ziehau /* $FreeBSD: src/sys/dev/msk/if_msk.c,v 1.26 2007/12/05 09:41:58 remko Exp $ */ 962d586421SSepherosa Ziehau 972d586421SSepherosa Ziehau /* 982d586421SSepherosa Ziehau * Device driver for the Marvell Yukon II Ethernet controller. 992d586421SSepherosa Ziehau * Due to lack of documentation, this driver is based on the code from 1002d586421SSepherosa Ziehau * sk(4) and Marvell's myk(4) driver for FreeBSD 5.x. 1012d586421SSepherosa Ziehau */ 1022d586421SSepherosa Ziehau 1032d586421SSepherosa Ziehau #include <sys/param.h> 1042d586421SSepherosa Ziehau #include <sys/endian.h> 1052d586421SSepherosa Ziehau #include <sys/kernel.h> 1062d586421SSepherosa Ziehau #include <sys/bus.h> 1072d586421SSepherosa Ziehau #include <sys/in_cksum.h> 1089db4b353SSepherosa Ziehau #include <sys/interrupt.h> 1092d586421SSepherosa Ziehau #include <sys/malloc.h> 1102d586421SSepherosa Ziehau #include <sys/proc.h> 1112d586421SSepherosa Ziehau #include <sys/rman.h> 1122d586421SSepherosa Ziehau #include <sys/serialize.h> 1132d586421SSepherosa Ziehau #include <sys/socket.h> 1142d586421SSepherosa Ziehau #include <sys/sockio.h> 1152d586421SSepherosa Ziehau #include <sys/sysctl.h> 1162d586421SSepherosa Ziehau 1172d586421SSepherosa Ziehau #include <net/ethernet.h> 1182d586421SSepherosa Ziehau #include <net/if.h> 1192d586421SSepherosa Ziehau #include <net/bpf.h> 1202d586421SSepherosa Ziehau #include <net/if_arp.h> 1212d586421SSepherosa Ziehau #include <net/if_dl.h> 1222d586421SSepherosa Ziehau #include <net/if_media.h> 1232d586421SSepherosa Ziehau #include <net/ifq_var.h> 1242d586421SSepherosa Ziehau #include <net/vlan/if_vlan_var.h> 1252d586421SSepherosa Ziehau 1262d586421SSepherosa Ziehau #include <netinet/ip.h> 1272d586421SSepherosa Ziehau #include <netinet/ip_var.h> 1282d586421SSepherosa Ziehau 1292d586421SSepherosa Ziehau #include <dev/netif/mii_layer/miivar.h> 1302d586421SSepherosa Ziehau 1312d586421SSepherosa Ziehau #include <bus/pci/pcireg.h> 1322d586421SSepherosa Ziehau #include <bus/pci/pcivar.h> 1332d586421SSepherosa Ziehau 1342d586421SSepherosa Ziehau #include "if_mskreg.h" 1352d586421SSepherosa Ziehau 1362d586421SSepherosa Ziehau /* "device miibus" required. See GENERIC if you get errors here. */ 1372d586421SSepherosa Ziehau #include "miibus_if.h" 1382d586421SSepherosa Ziehau 1392d586421SSepherosa Ziehau #define MSK_CSUM_FEATURES (CSUM_TCP | CSUM_UDP) 1402d586421SSepherosa Ziehau 1412d586421SSepherosa Ziehau /* 1422d586421SSepherosa Ziehau * Devices supported by this driver. 1432d586421SSepherosa Ziehau */ 1442d586421SSepherosa Ziehau static const struct msk_product { 1452d586421SSepherosa Ziehau uint16_t msk_vendorid; 1462d586421SSepherosa Ziehau uint16_t msk_deviceid; 1472d586421SSepherosa Ziehau const char *msk_name; 1482d586421SSepherosa Ziehau } msk_products[] = { 1492d586421SSepherosa Ziehau { VENDORID_SK, DEVICEID_SK_YUKON2, 1502d586421SSepherosa Ziehau "SK-9Sxx Gigabit Ethernet" }, 1512d586421SSepherosa Ziehau { VENDORID_SK, DEVICEID_SK_YUKON2_EXPR, 1522d586421SSepherosa Ziehau "SK-9Exx Gigabit Ethernet"}, 1532d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8021CU, 1542d586421SSepherosa Ziehau "Marvell Yukon 88E8021CU Gigabit Ethernet" }, 1552d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8021X, 1562d586421SSepherosa Ziehau "Marvell Yukon 88E8021 SX/LX Gigabit Ethernet" }, 1572d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8022CU, 1582d586421SSepherosa Ziehau "Marvell Yukon 88E8022CU Gigabit Ethernet" }, 1592d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8022X, 1602d586421SSepherosa Ziehau "Marvell Yukon 88E8022 SX/LX Gigabit Ethernet" }, 1612d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8061CU, 1622d586421SSepherosa Ziehau "Marvell Yukon 88E8061CU Gigabit Ethernet" }, 1632d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8061X, 1642d586421SSepherosa Ziehau "Marvell Yukon 88E8061 SX/LX Gigabit Ethernet" }, 1652d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8062CU, 1662d586421SSepherosa Ziehau "Marvell Yukon 88E8062CU Gigabit Ethernet" }, 1672d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8062X, 1682d586421SSepherosa Ziehau "Marvell Yukon 88E8062 SX/LX Gigabit Ethernet" }, 1692d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8035, 170b0968976SSepherosa Ziehau "Marvell Yukon 88E8035 Fast Ethernet" }, 1712d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8036, 172b0968976SSepherosa Ziehau "Marvell Yukon 88E8036 Fast Ethernet" }, 1732d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8038, 174b0968976SSepherosa Ziehau "Marvell Yukon 88E8038 Fast Ethernet" }, 1752d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8039, 176b0968976SSepherosa Ziehau "Marvell Yukon 88E8039 Fast Ethernet" }, 177080bd27eSSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8040, 178080bd27eSSepherosa Ziehau "Marvell Yukon 88E8040 Fast Ethernet" }, 179080bd27eSSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8040T, 180080bd27eSSepherosa Ziehau "Marvell Yukon 88E8040T Fast Ethernet" }, 181cb658b16SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8042, 182cb658b16SSepherosa Ziehau "Marvell Yukon 88E8042 Fast Ethernet" }, 183080bd27eSSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_8048, 184080bd27eSSepherosa Ziehau "Marvell Yukon 88E8048 Fast Ethernet" }, 1852d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4361, 1862d586421SSepherosa Ziehau "Marvell Yukon 88E8050 Gigabit Ethernet" }, 1872d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4360, 1882d586421SSepherosa Ziehau "Marvell Yukon 88E8052 Gigabit Ethernet" }, 1892d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4362, 1902d586421SSepherosa Ziehau "Marvell Yukon 88E8053 Gigabit Ethernet" }, 1912d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4363, 1922d586421SSepherosa Ziehau "Marvell Yukon 88E8055 Gigabit Ethernet" }, 1932d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4364, 1942d586421SSepherosa Ziehau "Marvell Yukon 88E8056 Gigabit Ethernet" }, 195d9e919c4SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4365, 196d9e919c4SSepherosa Ziehau "Marvell Yukon 88E8070 Gigabit Ethernet" }, 1972d586421SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_436A, 1982d586421SSepherosa Ziehau "Marvell Yukon 88E8058 Gigabit Ethernet" }, 199d9e919c4SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_436B, 200d9e919c4SSepherosa Ziehau "Marvell Yukon 88E8071 Gigabit Ethernet" }, 201d9e919c4SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_436C, 202d9e919c4SSepherosa Ziehau "Marvell Yukon 88E8072 Gigabit Ethernet" }, 2030d557164SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_436D, 2040d557164SSepherosa Ziehau "Marvell Yukon 88E8055 Gigabit Ethernet" }, 2050d557164SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4370, 2060d557164SSepherosa Ziehau "Marvell Yukon 88E8075 Gigabit Ethernet" }, 2073b7c5d2cSSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4380, 2083b7c5d2cSSepherosa Ziehau "Marvell Yukon 88E8057 Gigabit Ethernet" }, 2098e916b42SSepherosa Ziehau { VENDORID_MARVELL, DEVICEID_MRVL_4381, 2108e916b42SSepherosa Ziehau "Marvell Yukon 88E8059 Gigabit Ethernet" }, 2112d586421SSepherosa Ziehau { VENDORID_DLINK, DEVICEID_DLINK_DGE550SX, 2122d586421SSepherosa Ziehau "D-Link 550SX Gigabit Ethernet" }, 2132d586421SSepherosa Ziehau { VENDORID_DLINK, DEVICEID_DLINK_DGE560T, 2142d586421SSepherosa Ziehau "D-Link 560T Gigabit Ethernet" }, 2152d586421SSepherosa Ziehau { 0, 0, NULL } 2162d586421SSepherosa Ziehau }; 2172d586421SSepherosa Ziehau 2182d586421SSepherosa Ziehau static const char *model_name[] = { 2192d586421SSepherosa Ziehau "Yukon XL", 2202d586421SSepherosa Ziehau "Yukon EC Ultra", 221d9e919c4SSepherosa Ziehau "Yukon EX", 2222d586421SSepherosa Ziehau "Yukon EC", 223080bd27eSSepherosa Ziehau "Yukon FE", 2243b7c5d2cSSepherosa Ziehau "Yukon FE+", 2253b7c5d2cSSepherosa Ziehau "Yukon Supreme", 2268e916b42SSepherosa Ziehau "Yukon Ultra 2", 2278e916b42SSepherosa Ziehau "Yukon Unknown", 2288e916b42SSepherosa Ziehau "Yukon Optima" 2292d586421SSepherosa Ziehau }; 2302d586421SSepherosa Ziehau 2312d586421SSepherosa Ziehau static int mskc_probe(device_t); 2322d586421SSepherosa Ziehau static int mskc_attach(device_t); 2332d586421SSepherosa Ziehau static int mskc_detach(device_t); 2342d586421SSepherosa Ziehau static int mskc_shutdown(device_t); 2352d586421SSepherosa Ziehau static int mskc_suspend(device_t); 2362d586421SSepherosa Ziehau static int mskc_resume(device_t); 2372d586421SSepherosa Ziehau static void mskc_intr(void *); 2382d586421SSepherosa Ziehau 2392d586421SSepherosa Ziehau static void mskc_reset(struct msk_softc *); 240f59f1081SSepherosa Ziehau static void mskc_set_imtimer(struct msk_softc *); 2412d586421SSepherosa Ziehau static void mskc_intr_hwerr(struct msk_softc *); 2422d586421SSepherosa Ziehau static int mskc_handle_events(struct msk_softc *); 2432d586421SSepherosa Ziehau static void mskc_phy_power(struct msk_softc *, int); 2442d586421SSepherosa Ziehau static int mskc_setup_rambuffer(struct msk_softc *); 2452d586421SSepherosa Ziehau static int mskc_status_dma_alloc(struct msk_softc *); 2462d586421SSepherosa Ziehau static void mskc_status_dma_free(struct msk_softc *); 247f59f1081SSepherosa Ziehau static int mskc_sysctl_proc_limit(SYSCTL_HANDLER_ARGS); 248f59f1081SSepherosa Ziehau static int mskc_sysctl_intr_rate(SYSCTL_HANDLER_ARGS); 249f59f1081SSepherosa Ziehau 2502d586421SSepherosa Ziehau static int msk_probe(device_t); 2512d586421SSepherosa Ziehau static int msk_attach(device_t); 2522d586421SSepherosa Ziehau static int msk_detach(device_t); 2532d586421SSepherosa Ziehau static int msk_miibus_readreg(device_t, int, int); 2542d586421SSepherosa Ziehau static int msk_miibus_writereg(device_t, int, int, int); 2552d586421SSepherosa Ziehau static void msk_miibus_statchg(device_t); 2562d586421SSepherosa Ziehau 2572d586421SSepherosa Ziehau static void msk_init(void *); 2582d586421SSepherosa Ziehau static int msk_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 2592d586421SSepherosa Ziehau static void msk_start(struct ifnet *); 2602d586421SSepherosa Ziehau static void msk_watchdog(struct ifnet *); 2612d586421SSepherosa Ziehau static int msk_mediachange(struct ifnet *); 2622d586421SSepherosa Ziehau static void msk_mediastatus(struct ifnet *, struct ifmediareq *); 2632d586421SSepherosa Ziehau 2642d586421SSepherosa Ziehau static void msk_tick(void *); 2652d586421SSepherosa Ziehau static void msk_intr_phy(struct msk_if_softc *); 2662d586421SSepherosa Ziehau static void msk_intr_gmac(struct msk_if_softc *); 2672d586421SSepherosa Ziehau static __inline void 2682d586421SSepherosa Ziehau msk_rxput(struct msk_if_softc *); 2692d586421SSepherosa Ziehau static void msk_handle_hwerr(struct msk_if_softc *, uint32_t); 270eda7db08SSepherosa Ziehau static void msk_rxeof(struct msk_if_softc *, uint32_t, int); 2712d586421SSepherosa Ziehau static void msk_txeof(struct msk_if_softc *, int); 2722d586421SSepherosa Ziehau static void msk_set_prefetch(struct msk_softc *, int, bus_addr_t, uint32_t); 2732d586421SSepherosa Ziehau static void msk_set_rambuffer(struct msk_if_softc *); 2742d586421SSepherosa Ziehau static void msk_stop(struct msk_if_softc *); 2752d586421SSepherosa Ziehau 2762d586421SSepherosa Ziehau static int msk_txrx_dma_alloc(struct msk_if_softc *); 2772d586421SSepherosa Ziehau static void msk_txrx_dma_free(struct msk_if_softc *); 2782d586421SSepherosa Ziehau static int msk_init_rx_ring(struct msk_if_softc *); 2792d586421SSepherosa Ziehau static void msk_init_tx_ring(struct msk_if_softc *); 2802d586421SSepherosa Ziehau static __inline void 2812d586421SSepherosa Ziehau msk_discard_rxbuf(struct msk_if_softc *, int); 2822499c577SSepherosa Ziehau static int msk_newbuf(struct msk_if_softc *, int, int); 2832d586421SSepherosa Ziehau static int msk_encap(struct msk_if_softc *, struct mbuf **); 2842d586421SSepherosa Ziehau 2852d586421SSepherosa Ziehau #ifdef MSK_JUMBO 2862d586421SSepherosa Ziehau static int msk_init_jumbo_rx_ring(struct msk_if_softc *); 2872d586421SSepherosa Ziehau static __inline void msk_discard_jumbo_rxbuf(struct msk_if_softc *, int); 2882d586421SSepherosa Ziehau static int msk_jumbo_newbuf(struct msk_if_softc *, int); 2892d586421SSepherosa Ziehau static void msk_jumbo_rxeof(struct msk_if_softc *, uint32_t, int); 2902d586421SSepherosa Ziehau static void *msk_jalloc(struct msk_if_softc *); 2912d586421SSepherosa Ziehau static void msk_jfree(void *, void *); 2922d586421SSepherosa Ziehau #endif 2932d586421SSepherosa Ziehau 2942d586421SSepherosa Ziehau static int msk_phy_readreg(struct msk_if_softc *, int, int); 2952d586421SSepherosa Ziehau static int msk_phy_writereg(struct msk_if_softc *, int, int, int); 2962d586421SSepherosa Ziehau 297dc7303ffSSepherosa Ziehau static void msk_rxfilter(struct msk_if_softc *); 2982d586421SSepherosa Ziehau static void msk_setvlan(struct msk_if_softc *, struct ifnet *); 299d9e919c4SSepherosa Ziehau static void msk_set_tx_stfwd(struct msk_if_softc *); 3002d586421SSepherosa Ziehau 3012d586421SSepherosa Ziehau static int msk_dmamem_create(device_t, bus_size_t, bus_dma_tag_t *, 3022d586421SSepherosa Ziehau void **, bus_addr_t *, bus_dmamap_t *); 3032d586421SSepherosa Ziehau static void msk_dmamem_destroy(bus_dma_tag_t, void *, bus_dmamap_t); 3042d586421SSepherosa Ziehau 3052d586421SSepherosa Ziehau static device_method_t mskc_methods[] = { 3062d586421SSepherosa Ziehau /* Device interface */ 3072d586421SSepherosa Ziehau DEVMETHOD(device_probe, mskc_probe), 3082d586421SSepherosa Ziehau DEVMETHOD(device_attach, mskc_attach), 3092d586421SSepherosa Ziehau DEVMETHOD(device_detach, mskc_detach), 3102d586421SSepherosa Ziehau DEVMETHOD(device_suspend, mskc_suspend), 3112d586421SSepherosa Ziehau DEVMETHOD(device_resume, mskc_resume), 3122d586421SSepherosa Ziehau DEVMETHOD(device_shutdown, mskc_shutdown), 3132d586421SSepherosa Ziehau 3142d586421SSepherosa Ziehau /* bus interface */ 3152d586421SSepherosa Ziehau DEVMETHOD(bus_print_child, bus_generic_print_child), 3162d586421SSepherosa Ziehau DEVMETHOD(bus_driver_added, bus_generic_driver_added), 3172d586421SSepherosa Ziehau 3182d586421SSepherosa Ziehau { NULL, NULL } 3192d586421SSepherosa Ziehau }; 3202d586421SSepherosa Ziehau 3212d586421SSepherosa Ziehau static DEFINE_CLASS_0(mskc, mskc_driver, mskc_methods, sizeof(struct msk_softc)); 3222d586421SSepherosa Ziehau static devclass_t mskc_devclass; 3232d586421SSepherosa Ziehau 3242d586421SSepherosa Ziehau static device_method_t msk_methods[] = { 3252d586421SSepherosa Ziehau /* Device interface */ 3262d586421SSepherosa Ziehau DEVMETHOD(device_probe, msk_probe), 3272d586421SSepherosa Ziehau DEVMETHOD(device_attach, msk_attach), 3282d586421SSepherosa Ziehau DEVMETHOD(device_detach, msk_detach), 3292d586421SSepherosa Ziehau DEVMETHOD(device_shutdown, bus_generic_shutdown), 3302d586421SSepherosa Ziehau 3312d586421SSepherosa Ziehau /* bus interface */ 3322d586421SSepherosa Ziehau DEVMETHOD(bus_print_child, bus_generic_print_child), 3332d586421SSepherosa Ziehau DEVMETHOD(bus_driver_added, bus_generic_driver_added), 3342d586421SSepherosa Ziehau 3352d586421SSepherosa Ziehau /* MII interface */ 3362d586421SSepherosa Ziehau DEVMETHOD(miibus_readreg, msk_miibus_readreg), 3372d586421SSepherosa Ziehau DEVMETHOD(miibus_writereg, msk_miibus_writereg), 3382d586421SSepherosa Ziehau DEVMETHOD(miibus_statchg, msk_miibus_statchg), 3392d586421SSepherosa Ziehau 3402d586421SSepherosa Ziehau { NULL, NULL } 3412d586421SSepherosa Ziehau }; 3422d586421SSepherosa Ziehau 3432d586421SSepherosa Ziehau static DEFINE_CLASS_0(msk, msk_driver, msk_methods, sizeof(struct msk_if_softc)); 3442d586421SSepherosa Ziehau static devclass_t msk_devclass; 3452d586421SSepherosa Ziehau 3462d586421SSepherosa Ziehau DECLARE_DUMMY_MODULE(if_msk); 347aa2b9d05SSascha Wildner DRIVER_MODULE(if_msk, pci, mskc_driver, mskc_devclass, NULL, NULL); 348aa2b9d05SSascha Wildner DRIVER_MODULE(if_msk, mskc, msk_driver, msk_devclass, NULL, NULL); 349aa2b9d05SSascha Wildner DRIVER_MODULE(miibus, msk, miibus_driver, miibus_devclass, NULL, NULL); 3502d586421SSepherosa Ziehau 351f59f1081SSepherosa Ziehau static int mskc_intr_rate = 0; 352f59f1081SSepherosa Ziehau static int mskc_process_limit = MSK_PROC_DEFAULT; 353f59f1081SSepherosa Ziehau 354f59f1081SSepherosa Ziehau TUNABLE_INT("hw.mskc.intr_rate", &mskc_intr_rate); 355f59f1081SSepherosa Ziehau TUNABLE_INT("hw.mskc.process_limit", &mskc_process_limit); 356f59f1081SSepherosa Ziehau 3572d586421SSepherosa Ziehau static int 3582d586421SSepherosa Ziehau msk_miibus_readreg(device_t dev, int phy, int reg) 3592d586421SSepherosa Ziehau { 3602d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 3612d586421SSepherosa Ziehau 3622d586421SSepherosa Ziehau if (phy != PHY_ADDR_MARV) 3632d586421SSepherosa Ziehau return (0); 3642d586421SSepherosa Ziehau 3652d586421SSepherosa Ziehau sc_if = device_get_softc(dev); 3662d586421SSepherosa Ziehau 3672d586421SSepherosa Ziehau return (msk_phy_readreg(sc_if, phy, reg)); 3682d586421SSepherosa Ziehau } 3692d586421SSepherosa Ziehau 3702d586421SSepherosa Ziehau static int 3712d586421SSepherosa Ziehau msk_phy_readreg(struct msk_if_softc *sc_if, int phy, int reg) 3722d586421SSepherosa Ziehau { 3732d586421SSepherosa Ziehau struct msk_softc *sc; 3742d586421SSepherosa Ziehau int i, val; 3752d586421SSepherosa Ziehau 3762d586421SSepherosa Ziehau sc = sc_if->msk_softc; 3772d586421SSepherosa Ziehau 3782d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_SMI_CTRL, 3792d586421SSepherosa Ziehau GM_SMI_CT_PHY_AD(phy) | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); 3802d586421SSepherosa Ziehau 3812d586421SSepherosa Ziehau for (i = 0; i < MSK_TIMEOUT; i++) { 3822d586421SSepherosa Ziehau DELAY(1); 3832d586421SSepherosa Ziehau val = GMAC_READ_2(sc, sc_if->msk_port, GM_SMI_CTRL); 3842d586421SSepherosa Ziehau if ((val & GM_SMI_CT_RD_VAL) != 0) { 3852d586421SSepherosa Ziehau val = GMAC_READ_2(sc, sc_if->msk_port, GM_SMI_DATA); 3862d586421SSepherosa Ziehau break; 3872d586421SSepherosa Ziehau } 3882d586421SSepherosa Ziehau } 3892d586421SSepherosa Ziehau 3902d586421SSepherosa Ziehau if (i == MSK_TIMEOUT) { 3912d586421SSepherosa Ziehau if_printf(sc_if->msk_ifp, "phy failed to come ready\n"); 3922d586421SSepherosa Ziehau val = 0; 3932d586421SSepherosa Ziehau } 3942d586421SSepherosa Ziehau 3952d586421SSepherosa Ziehau return (val); 3962d586421SSepherosa Ziehau } 3972d586421SSepherosa Ziehau 3982d586421SSepherosa Ziehau static int 3992d586421SSepherosa Ziehau msk_miibus_writereg(device_t dev, int phy, int reg, int val) 4002d586421SSepherosa Ziehau { 4012d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 4022d586421SSepherosa Ziehau 4032d586421SSepherosa Ziehau if (phy != PHY_ADDR_MARV) 4042d586421SSepherosa Ziehau return (0); 4052d586421SSepherosa Ziehau 4062d586421SSepherosa Ziehau sc_if = device_get_softc(dev); 4072d586421SSepherosa Ziehau 4082d586421SSepherosa Ziehau return (msk_phy_writereg(sc_if, phy, reg, val)); 4092d586421SSepherosa Ziehau } 4102d586421SSepherosa Ziehau 4112d586421SSepherosa Ziehau static int 4122d586421SSepherosa Ziehau msk_phy_writereg(struct msk_if_softc *sc_if, int phy, int reg, int val) 4132d586421SSepherosa Ziehau { 4142d586421SSepherosa Ziehau struct msk_softc *sc; 4152d586421SSepherosa Ziehau int i; 4162d586421SSepherosa Ziehau 4172d586421SSepherosa Ziehau sc = sc_if->msk_softc; 4182d586421SSepherosa Ziehau 4192d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_SMI_DATA, val); 4202d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_SMI_CTRL, 4212d586421SSepherosa Ziehau GM_SMI_CT_PHY_AD(phy) | GM_SMI_CT_REG_AD(reg)); 4222d586421SSepherosa Ziehau for (i = 0; i < MSK_TIMEOUT; i++) { 4232d586421SSepherosa Ziehau DELAY(1); 4242d586421SSepherosa Ziehau if ((GMAC_READ_2(sc, sc_if->msk_port, GM_SMI_CTRL) & 4252d586421SSepherosa Ziehau GM_SMI_CT_BUSY) == 0) 4262d586421SSepherosa Ziehau break; 4272d586421SSepherosa Ziehau } 4282d586421SSepherosa Ziehau if (i == MSK_TIMEOUT) 4292d586421SSepherosa Ziehau if_printf(sc_if->msk_ifp, "phy write timeout\n"); 4302d586421SSepherosa Ziehau 4312d586421SSepherosa Ziehau return (0); 4322d586421SSepherosa Ziehau } 4332d586421SSepherosa Ziehau 4342d586421SSepherosa Ziehau static void 4352d586421SSepherosa Ziehau msk_miibus_statchg(device_t dev) 4362d586421SSepherosa Ziehau { 4372d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 4382d586421SSepherosa Ziehau struct msk_softc *sc; 4392d586421SSepherosa Ziehau struct mii_data *mii; 4402d586421SSepherosa Ziehau struct ifnet *ifp; 4412d586421SSepherosa Ziehau uint32_t gmac; 4422d586421SSepherosa Ziehau 4432d586421SSepherosa Ziehau sc_if = device_get_softc(dev); 4442d586421SSepherosa Ziehau sc = sc_if->msk_softc; 4452d586421SSepherosa Ziehau 4462d586421SSepherosa Ziehau mii = device_get_softc(sc_if->msk_miibus); 4472d586421SSepherosa Ziehau ifp = sc_if->msk_ifp; 4482d586421SSepherosa Ziehau 4492d586421SSepherosa Ziehau sc_if->msk_link = 0; 4504992f870SSepherosa Ziehau if ((mii->mii_media_status & (IFM_AVALID | IFM_ACTIVE)) == 4514992f870SSepherosa Ziehau (IFM_AVALID | IFM_ACTIVE)) { 4524992f870SSepherosa Ziehau switch (IFM_SUBTYPE(mii->mii_media_active)) { 4534992f870SSepherosa Ziehau case IFM_10_T: 4544992f870SSepherosa Ziehau case IFM_100_TX: 4554992f870SSepherosa Ziehau sc_if->msk_link = 1; 4564992f870SSepherosa Ziehau break; 4574992f870SSepherosa Ziehau case IFM_1000_T: 4584992f870SSepherosa Ziehau case IFM_1000_SX: 4594992f870SSepherosa Ziehau case IFM_1000_LX: 4604992f870SSepherosa Ziehau case IFM_1000_CX: 4614992f870SSepherosa Ziehau if ((sc_if->msk_flags & MSK_FLAG_FASTETHER) == 0) 4624992f870SSepherosa Ziehau sc_if->msk_link = 1; 4634992f870SSepherosa Ziehau break; 4644992f870SSepherosa Ziehau } 4654992f870SSepherosa Ziehau } 4662d586421SSepherosa Ziehau 4672d586421SSepherosa Ziehau if (sc_if->msk_link != 0) { 4682d586421SSepherosa Ziehau /* Enable Tx FIFO Underrun. */ 4692d586421SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, GMAC_IRQ_MSK), 4702d586421SSepherosa Ziehau GM_IS_TX_FF_UR | GM_IS_RX_FF_OR); 4712d586421SSepherosa Ziehau /* 4722d586421SSepherosa Ziehau * Because mii(4) notify msk(4) that it detected link status 4732d586421SSepherosa Ziehau * change, there is no need to enable automatic 4742d586421SSepherosa Ziehau * speed/flow-control/duplex updates. 4752d586421SSepherosa Ziehau */ 4762d586421SSepherosa Ziehau gmac = GM_GPCR_AU_ALL_DIS; 4772d586421SSepherosa Ziehau switch (IFM_SUBTYPE(mii->mii_media_active)) { 4782d586421SSepherosa Ziehau case IFM_1000_SX: 4792d586421SSepherosa Ziehau case IFM_1000_T: 4802d586421SSepherosa Ziehau gmac |= GM_GPCR_SPEED_1000; 4812d586421SSepherosa Ziehau break; 4822d586421SSepherosa Ziehau case IFM_100_TX: 4832d586421SSepherosa Ziehau gmac |= GM_GPCR_SPEED_100; 4842d586421SSepherosa Ziehau break; 4852d586421SSepherosa Ziehau case IFM_10_T: 4862d586421SSepherosa Ziehau break; 4872d586421SSepherosa Ziehau } 4882d586421SSepherosa Ziehau 4898f5842deSSepherosa Ziehau if ((mii->mii_media_active & IFM_GMASK) & IFM_FDX) 4902d586421SSepherosa Ziehau gmac |= GM_GPCR_DUP_FULL; 4918f5842deSSepherosa Ziehau else 4928f5842deSSepherosa Ziehau gmac |= GM_GPCR_FC_RX_DIS | GM_GPCR_FC_TX_DIS; 4932d586421SSepherosa Ziehau /* Disable Rx flow control. */ 4942d586421SSepherosa Ziehau if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG0) == 0) 4952d586421SSepherosa Ziehau gmac |= GM_GPCR_FC_RX_DIS; 4962d586421SSepherosa Ziehau /* Disable Tx flow control. */ 4972d586421SSepherosa Ziehau if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG1) == 0) 4982d586421SSepherosa Ziehau gmac |= GM_GPCR_FC_TX_DIS; 4992d586421SSepherosa Ziehau gmac |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; 5002d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, gmac); 5012d586421SSepherosa Ziehau /* Read again to ensure writing. */ 5022d586421SSepherosa Ziehau GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL); 5032d586421SSepherosa Ziehau 5048f5842deSSepherosa Ziehau gmac = GMC_PAUSE_OFF; 5058f5842deSSepherosa Ziehau if (((mii->mii_media_active & IFM_GMASK) & IFM_FLAG0) && 5068f5842deSSepherosa Ziehau ((mii->mii_media_active & IFM_GMASK) & IFM_FDX)) 5072d586421SSepherosa Ziehau gmac = GMC_PAUSE_ON; 5082d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), gmac); 5092d586421SSepherosa Ziehau 5102d586421SSepherosa Ziehau /* Enable PHY interrupt for FIFO underrun/overflow. */ 5112d586421SSepherosa Ziehau msk_phy_writereg(sc_if, PHY_ADDR_MARV, 5122d586421SSepherosa Ziehau PHY_MARV_INT_MASK, PHY_M_IS_FIFO_ERROR); 5132d586421SSepherosa Ziehau } else { 5142d586421SSepherosa Ziehau /* 5152d586421SSepherosa Ziehau * Link state changed to down. 5162d586421SSepherosa Ziehau * Disable PHY interrupts. 5172d586421SSepherosa Ziehau */ 5182d586421SSepherosa Ziehau msk_phy_writereg(sc_if, PHY_ADDR_MARV, PHY_MARV_INT_MASK, 0); 5192d586421SSepherosa Ziehau /* Disable Rx/Tx MAC. */ 5202d586421SSepherosa Ziehau gmac = GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL); 52153f9b600SSepherosa Ziehau if (gmac & (GM_GPCR_RX_ENA | GM_GPCR_TX_ENA)) { 5222d586421SSepherosa Ziehau gmac &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); 5232d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, gmac); 5242d586421SSepherosa Ziehau /* Read again to ensure writing. */ 5252d586421SSepherosa Ziehau GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL); 5262d586421SSepherosa Ziehau } 5272d586421SSepherosa Ziehau } 52853f9b600SSepherosa Ziehau } 5292d586421SSepherosa Ziehau 5302d586421SSepherosa Ziehau static void 531dc7303ffSSepherosa Ziehau msk_rxfilter(struct msk_if_softc *sc_if) 5322d586421SSepherosa Ziehau { 5332d586421SSepherosa Ziehau struct msk_softc *sc; 5342d586421SSepherosa Ziehau struct ifnet *ifp; 5352d586421SSepherosa Ziehau struct ifmultiaddr *ifma; 5362d586421SSepherosa Ziehau uint32_t mchash[2]; 5372d586421SSepherosa Ziehau uint32_t crc; 5382d586421SSepherosa Ziehau uint16_t mode; 5392d586421SSepherosa Ziehau 5402d586421SSepherosa Ziehau sc = sc_if->msk_softc; 5412d586421SSepherosa Ziehau ifp = sc_if->msk_ifp; 5422d586421SSepherosa Ziehau 5432d586421SSepherosa Ziehau bzero(mchash, sizeof(mchash)); 5442d586421SSepherosa Ziehau mode = GMAC_READ_2(sc, sc_if->msk_port, GM_RX_CTRL); 545dc7303ffSSepherosa Ziehau if ((ifp->if_flags & IFF_PROMISC) != 0) { 5462d586421SSepherosa Ziehau mode &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); 547dc7303ffSSepherosa Ziehau } else if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 548dc7303ffSSepherosa Ziehau mode |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); 5492d586421SSepherosa Ziehau mchash[0] = 0xffff; 5502d586421SSepherosa Ziehau mchash[1] = 0xffff; 5512d586421SSepherosa Ziehau } else { 552dc7303ffSSepherosa Ziehau mode |= GM_RXCR_UCF_ENA; 553441d34b2SSascha Wildner TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 5542d586421SSepherosa Ziehau if (ifma->ifma_addr->sa_family != AF_LINK) 5552d586421SSepherosa Ziehau continue; 5562d586421SSepherosa Ziehau crc = ether_crc32_be(LLADDR((struct sockaddr_dl *) 5572d586421SSepherosa Ziehau ifma->ifma_addr), ETHER_ADDR_LEN); 5582d586421SSepherosa Ziehau /* Just want the 6 least significant bits. */ 5592d586421SSepherosa Ziehau crc &= 0x3f; 5602d586421SSepherosa Ziehau /* Set the corresponding bit in the hash table. */ 5612d586421SSepherosa Ziehau mchash[crc >> 5] |= 1 << (crc & 0x1f); 5622d586421SSepherosa Ziehau } 563dc7303ffSSepherosa Ziehau if (mchash[0] != 0 || mchash[1] != 0) 5642d586421SSepherosa Ziehau mode |= GM_RXCR_MCF_ENA; 5652d586421SSepherosa Ziehau } 5662d586421SSepherosa Ziehau 5672d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_MC_ADDR_H1, 5682d586421SSepherosa Ziehau mchash[0] & 0xffff); 5692d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_MC_ADDR_H2, 5702d586421SSepherosa Ziehau (mchash[0] >> 16) & 0xffff); 5712d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_MC_ADDR_H3, 5722d586421SSepherosa Ziehau mchash[1] & 0xffff); 5732d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_MC_ADDR_H4, 5742d586421SSepherosa Ziehau (mchash[1] >> 16) & 0xffff); 5752d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_RX_CTRL, mode); 5762d586421SSepherosa Ziehau } 5772d586421SSepherosa Ziehau 5782d586421SSepherosa Ziehau static void 5792d586421SSepherosa Ziehau msk_setvlan(struct msk_if_softc *sc_if, struct ifnet *ifp) 5802d586421SSepherosa Ziehau { 5812d586421SSepherosa Ziehau struct msk_softc *sc; 5822d586421SSepherosa Ziehau 5832d586421SSepherosa Ziehau sc = sc_if->msk_softc; 5842d586421SSepherosa Ziehau if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) { 5852d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), 5862d586421SSepherosa Ziehau RX_VLAN_STRIP_ON); 5872d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), 5882d586421SSepherosa Ziehau TX_VLAN_TAG_ON); 5892d586421SSepherosa Ziehau } else { 5902d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), 5912d586421SSepherosa Ziehau RX_VLAN_STRIP_OFF); 5922d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), 5932d586421SSepherosa Ziehau TX_VLAN_TAG_OFF); 5942d586421SSepherosa Ziehau } 5952d586421SSepherosa Ziehau } 5962d586421SSepherosa Ziehau 5972d586421SSepherosa Ziehau static int 5982d586421SSepherosa Ziehau msk_init_rx_ring(struct msk_if_softc *sc_if) 5992d586421SSepherosa Ziehau { 6002d586421SSepherosa Ziehau struct msk_ring_data *rd; 6012d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 6022d586421SSepherosa Ziehau int i, prod; 6032d586421SSepherosa Ziehau 6042d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_cons = 0; 6052d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_prod = 0; 6062d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_putwm = MSK_PUT_WM; 6072d586421SSepherosa Ziehau 6082d586421SSepherosa Ziehau rd = &sc_if->msk_rdata; 6092d586421SSepherosa Ziehau bzero(rd->msk_rx_ring, sizeof(struct msk_rx_desc) * MSK_RX_RING_CNT); 6102d586421SSepherosa Ziehau prod = sc_if->msk_cdata.msk_rx_prod; 6112d586421SSepherosa Ziehau for (i = 0; i < MSK_RX_RING_CNT; i++) { 6122d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[prod]; 6132d586421SSepherosa Ziehau rxd->rx_m = NULL; 6142d586421SSepherosa Ziehau rxd->rx_le = &rd->msk_rx_ring[prod]; 6152499c577SSepherosa Ziehau if (msk_newbuf(sc_if, prod, 1) != 0) 6162d586421SSepherosa Ziehau return (ENOBUFS); 6172d586421SSepherosa Ziehau MSK_INC(prod, MSK_RX_RING_CNT); 6182d586421SSepherosa Ziehau } 6192d586421SSepherosa Ziehau 6202d586421SSepherosa Ziehau /* Update prefetch unit. */ 6212d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_prod = MSK_RX_RING_CNT - 1; 6222d586421SSepherosa Ziehau CSR_WRITE_2(sc_if->msk_softc, 6232d586421SSepherosa Ziehau Y2_PREF_Q_ADDR(sc_if->msk_rxq, PREF_UNIT_PUT_IDX_REG), 6242d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_prod); 6252d586421SSepherosa Ziehau 6262d586421SSepherosa Ziehau return (0); 6272d586421SSepherosa Ziehau } 6282d586421SSepherosa Ziehau 6292d586421SSepherosa Ziehau #ifdef MSK_JUMBO 6302d586421SSepherosa Ziehau static int 6312d586421SSepherosa Ziehau msk_init_jumbo_rx_ring(struct msk_if_softc *sc_if) 6322d586421SSepherosa Ziehau { 6332d586421SSepherosa Ziehau struct msk_ring_data *rd; 6342d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 6352d586421SSepherosa Ziehau int i, prod; 6362d586421SSepherosa Ziehau 6372d586421SSepherosa Ziehau MSK_IF_LOCK_ASSERT(sc_if); 6382d586421SSepherosa Ziehau 6392d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_cons = 0; 6402d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_prod = 0; 6412d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_putwm = MSK_PUT_WM; 6422d586421SSepherosa Ziehau 6432d586421SSepherosa Ziehau rd = &sc_if->msk_rdata; 6442d586421SSepherosa Ziehau bzero(rd->msk_jumbo_rx_ring, 6452d586421SSepherosa Ziehau sizeof(struct msk_rx_desc) * MSK_JUMBO_RX_RING_CNT); 6462d586421SSepherosa Ziehau prod = sc_if->msk_cdata.msk_rx_prod; 6472d586421SSepherosa Ziehau for (i = 0; i < MSK_JUMBO_RX_RING_CNT; i++) { 6482d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[prod]; 6492d586421SSepherosa Ziehau rxd->rx_m = NULL; 6502d586421SSepherosa Ziehau rxd->rx_le = &rd->msk_jumbo_rx_ring[prod]; 6512d586421SSepherosa Ziehau if (msk_jumbo_newbuf(sc_if, prod) != 0) 6522d586421SSepherosa Ziehau return (ENOBUFS); 6532d586421SSepherosa Ziehau MSK_INC(prod, MSK_JUMBO_RX_RING_CNT); 6542d586421SSepherosa Ziehau } 6552d586421SSepherosa Ziehau 6562d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, 6572d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_map, 6582d586421SSepherosa Ziehau BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 6592d586421SSepherosa Ziehau 6602d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_prod = MSK_JUMBO_RX_RING_CNT - 1; 6612d586421SSepherosa Ziehau CSR_WRITE_2(sc_if->msk_softc, 6622d586421SSepherosa Ziehau Y2_PREF_Q_ADDR(sc_if->msk_rxq, PREF_UNIT_PUT_IDX_REG), 6632d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_prod); 6642d586421SSepherosa Ziehau 6652d586421SSepherosa Ziehau return (0); 6662d586421SSepherosa Ziehau } 6672d586421SSepherosa Ziehau #endif 6682d586421SSepherosa Ziehau 6692d586421SSepherosa Ziehau static void 6702d586421SSepherosa Ziehau msk_init_tx_ring(struct msk_if_softc *sc_if) 6712d586421SSepherosa Ziehau { 6722d586421SSepherosa Ziehau struct msk_ring_data *rd; 6732d586421SSepherosa Ziehau struct msk_txdesc *txd; 6742d586421SSepherosa Ziehau int i; 6752d586421SSepherosa Ziehau 6762d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_prod = 0; 6772d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cons = 0; 6782d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cnt = 0; 6792d586421SSepherosa Ziehau 6802d586421SSepherosa Ziehau rd = &sc_if->msk_rdata; 6812d586421SSepherosa Ziehau bzero(rd->msk_tx_ring, sizeof(struct msk_tx_desc) * MSK_TX_RING_CNT); 6822d586421SSepherosa Ziehau for (i = 0; i < MSK_TX_RING_CNT; i++) { 6832d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[i]; 6842d586421SSepherosa Ziehau txd->tx_m = NULL; 6852d586421SSepherosa Ziehau txd->tx_le = &rd->msk_tx_ring[i]; 6862d586421SSepherosa Ziehau } 6872d586421SSepherosa Ziehau } 6882d586421SSepherosa Ziehau 6892d586421SSepherosa Ziehau static __inline void 6902d586421SSepherosa Ziehau msk_discard_rxbuf(struct msk_if_softc *sc_if, int idx) 6912d586421SSepherosa Ziehau { 6922d586421SSepherosa Ziehau struct msk_rx_desc *rx_le; 6932d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 6942d586421SSepherosa Ziehau struct mbuf *m; 6952d586421SSepherosa Ziehau 6962d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[idx]; 6972d586421SSepherosa Ziehau m = rxd->rx_m; 6982d586421SSepherosa Ziehau rx_le = rxd->rx_le; 6992d586421SSepherosa Ziehau rx_le->msk_control = htole32(m->m_len | OP_PACKET | HW_OWNER); 7002d586421SSepherosa Ziehau } 7012d586421SSepherosa Ziehau 7022d586421SSepherosa Ziehau #ifdef MSK_JUMBO 7032d586421SSepherosa Ziehau static __inline void 7042d586421SSepherosa Ziehau msk_discard_jumbo_rxbuf(struct msk_if_softc *sc_if, int idx) 7052d586421SSepherosa Ziehau { 7062d586421SSepherosa Ziehau struct msk_rx_desc *rx_le; 7072d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 7082d586421SSepherosa Ziehau struct mbuf *m; 7092d586421SSepherosa Ziehau 7102d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[idx]; 7112d586421SSepherosa Ziehau m = rxd->rx_m; 7122d586421SSepherosa Ziehau rx_le = rxd->rx_le; 7132d586421SSepherosa Ziehau rx_le->msk_control = htole32(m->m_len | OP_PACKET | HW_OWNER); 7142d586421SSepherosa Ziehau } 7152d586421SSepherosa Ziehau #endif 7162d586421SSepherosa Ziehau 7172d586421SSepherosa Ziehau static int 7182499c577SSepherosa Ziehau msk_newbuf(struct msk_if_softc *sc_if, int idx, int init) 7192d586421SSepherosa Ziehau { 7202d586421SSepherosa Ziehau struct msk_rx_desc *rx_le; 7212d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 7222d586421SSepherosa Ziehau struct mbuf *m; 7232d586421SSepherosa Ziehau bus_dma_segment_t seg; 7242d586421SSepherosa Ziehau bus_dmamap_t map; 7252499c577SSepherosa Ziehau int error, nseg; 7262d586421SSepherosa Ziehau 7272499c577SSepherosa Ziehau m = m_getcl(init ? MB_WAIT : MB_DONTWAIT, MT_DATA, M_PKTHDR); 7282d586421SSepherosa Ziehau if (m == NULL) 7292d586421SSepherosa Ziehau return (ENOBUFS); 7302d586421SSepherosa Ziehau 7312d586421SSepherosa Ziehau m->m_len = m->m_pkthdr.len = MCLBYTES; 7322a9b20a4SSepherosa Ziehau if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0) 7332d586421SSepherosa Ziehau m_adj(m, ETHER_ALIGN); 7342d586421SSepherosa Ziehau 7352499c577SSepherosa Ziehau error = bus_dmamap_load_mbuf_segment(sc_if->msk_cdata.msk_rx_tag, 7362499c577SSepherosa Ziehau sc_if->msk_cdata.msk_rx_sparemap, 7372499c577SSepherosa Ziehau m, &seg, 1, &nseg, BUS_DMA_NOWAIT); 7382499c577SSepherosa Ziehau if (error) { 7392d586421SSepherosa Ziehau m_freem(m); 7402499c577SSepherosa Ziehau if (init) 7412499c577SSepherosa Ziehau if_printf(&sc_if->arpcom.ac_if, "can't load RX mbuf\n"); 7422499c577SSepherosa Ziehau return (error); 7432d586421SSepherosa Ziehau } 7442d586421SSepherosa Ziehau 7452d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[idx]; 7462d586421SSepherosa Ziehau if (rxd->rx_m != NULL) { 7472d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_rx_tag, rxd->rx_dmamap, 7482d586421SSepherosa Ziehau BUS_DMASYNC_POSTREAD); 7492d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_rx_tag, rxd->rx_dmamap); 7502d586421SSepherosa Ziehau } 7512499c577SSepherosa Ziehau 7522d586421SSepherosa Ziehau map = rxd->rx_dmamap; 7532d586421SSepherosa Ziehau rxd->rx_dmamap = sc_if->msk_cdata.msk_rx_sparemap; 7542d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_sparemap = map; 7552499c577SSepherosa Ziehau 7562d586421SSepherosa Ziehau rxd->rx_m = m; 7572d586421SSepherosa Ziehau rx_le = rxd->rx_le; 7582d586421SSepherosa Ziehau rx_le->msk_addr = htole32(MSK_ADDR_LO(seg.ds_addr)); 7592499c577SSepherosa Ziehau rx_le->msk_control = htole32(seg.ds_len | OP_PACKET | HW_OWNER); 7602d586421SSepherosa Ziehau 7612d586421SSepherosa Ziehau return (0); 7622d586421SSepherosa Ziehau } 7632d586421SSepherosa Ziehau 7642d586421SSepherosa Ziehau #ifdef MSK_JUMBO 7652d586421SSepherosa Ziehau static int 7662d586421SSepherosa Ziehau msk_jumbo_newbuf(struct msk_if_softc *sc_if, int idx) 7672d586421SSepherosa Ziehau { 7682d586421SSepherosa Ziehau struct msk_rx_desc *rx_le; 7692d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 7702d586421SSepherosa Ziehau struct mbuf *m; 7712d586421SSepherosa Ziehau bus_dma_segment_t segs[1]; 7722d586421SSepherosa Ziehau bus_dmamap_t map; 7732d586421SSepherosa Ziehau int nsegs; 7742d586421SSepherosa Ziehau void *buf; 7752d586421SSepherosa Ziehau 7765113665dSNuno Antunes MGETHDR(m, MB_DONTWAIT, MT_DATA); 7772d586421SSepherosa Ziehau if (m == NULL) 7782d586421SSepherosa Ziehau return (ENOBUFS); 7792d586421SSepherosa Ziehau buf = msk_jalloc(sc_if); 7802d586421SSepherosa Ziehau if (buf == NULL) { 7812d586421SSepherosa Ziehau m_freem(m); 7822d586421SSepherosa Ziehau return (ENOBUFS); 7832d586421SSepherosa Ziehau } 7842d586421SSepherosa Ziehau /* Attach the buffer to the mbuf. */ 78534b49ab5SSascha Wildner MEXTADD(m, buf, MSK_JLEN, msk_jfree, sc_if, 0, EXT_NET_DRV); 7862d586421SSepherosa Ziehau if ((m->m_flags & M_EXT) == 0) { 7872d586421SSepherosa Ziehau m_freem(m); 7882d586421SSepherosa Ziehau return (ENOBUFS); 7892d586421SSepherosa Ziehau } 7902d586421SSepherosa Ziehau m->m_pkthdr.len = m->m_len = MSK_JLEN; 7912d586421SSepherosa Ziehau m_adj(m, ETHER_ALIGN); 7922d586421SSepherosa Ziehau 7932d586421SSepherosa Ziehau if (bus_dmamap_load_mbuf_sg(sc_if->msk_cdata.msk_jumbo_rx_tag, 7942d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_sparemap, m, segs, &nsegs, 7952d586421SSepherosa Ziehau BUS_DMA_NOWAIT) != 0) { 7962d586421SSepherosa Ziehau m_freem(m); 7972d586421SSepherosa Ziehau return (ENOBUFS); 7982d586421SSepherosa Ziehau } 7992d586421SSepherosa Ziehau KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 8002d586421SSepherosa Ziehau 8012d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[idx]; 8022d586421SSepherosa Ziehau if (rxd->rx_m != NULL) { 8032d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_jumbo_rx_tag, 8042d586421SSepherosa Ziehau rxd->rx_dmamap, BUS_DMASYNC_POSTREAD); 8052d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_jumbo_rx_tag, 8062d586421SSepherosa Ziehau rxd->rx_dmamap); 8072d586421SSepherosa Ziehau } 8082d586421SSepherosa Ziehau map = rxd->rx_dmamap; 8092d586421SSepherosa Ziehau rxd->rx_dmamap = sc_if->msk_cdata.msk_jumbo_rx_sparemap; 8102d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_sparemap = map; 8112d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_jumbo_rx_tag, rxd->rx_dmamap, 8122d586421SSepherosa Ziehau BUS_DMASYNC_PREREAD); 8132d586421SSepherosa Ziehau rxd->rx_m = m; 8142d586421SSepherosa Ziehau rx_le = rxd->rx_le; 8152d586421SSepherosa Ziehau rx_le->msk_addr = htole32(MSK_ADDR_LO(segs[0].ds_addr)); 8162d586421SSepherosa Ziehau rx_le->msk_control = 8172d586421SSepherosa Ziehau htole32(segs[0].ds_len | OP_PACKET | HW_OWNER); 8182d586421SSepherosa Ziehau 8192d586421SSepherosa Ziehau return (0); 8202d586421SSepherosa Ziehau } 8212d586421SSepherosa Ziehau #endif 8222d586421SSepherosa Ziehau 8232d586421SSepherosa Ziehau /* 8242d586421SSepherosa Ziehau * Set media options. 8252d586421SSepherosa Ziehau */ 8262d586421SSepherosa Ziehau static int 8272d586421SSepherosa Ziehau msk_mediachange(struct ifnet *ifp) 8282d586421SSepherosa Ziehau { 8292d586421SSepherosa Ziehau struct msk_if_softc *sc_if = ifp->if_softc; 8302d586421SSepherosa Ziehau struct mii_data *mii; 83118804a77SSepherosa Ziehau int error; 8322d586421SSepherosa Ziehau 8332d586421SSepherosa Ziehau mii = device_get_softc(sc_if->msk_miibus); 83418804a77SSepherosa Ziehau error = mii_mediachg(mii); 8352d586421SSepherosa Ziehau 83618804a77SSepherosa Ziehau return (error); 8372d586421SSepherosa Ziehau } 8382d586421SSepherosa Ziehau 8392d586421SSepherosa Ziehau /* 8402d586421SSepherosa Ziehau * Report current media status. 8412d586421SSepherosa Ziehau */ 8422d586421SSepherosa Ziehau static void 8432d586421SSepherosa Ziehau msk_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 8442d586421SSepherosa Ziehau { 8452d586421SSepherosa Ziehau struct msk_if_softc *sc_if = ifp->if_softc; 8462d586421SSepherosa Ziehau struct mii_data *mii; 8472d586421SSepherosa Ziehau 8482d586421SSepherosa Ziehau mii = device_get_softc(sc_if->msk_miibus); 8492d586421SSepherosa Ziehau mii_pollstat(mii); 8502d586421SSepherosa Ziehau 8512d586421SSepherosa Ziehau ifmr->ifm_active = mii->mii_media_active; 8522d586421SSepherosa Ziehau ifmr->ifm_status = mii->mii_media_status; 8532d586421SSepherosa Ziehau } 8542d586421SSepherosa Ziehau 8552d586421SSepherosa Ziehau static int 8562d586421SSepherosa Ziehau msk_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) 8572d586421SSepherosa Ziehau { 8582d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 8592d586421SSepherosa Ziehau struct ifreq *ifr; 8602d586421SSepherosa Ziehau struct mii_data *mii; 8612d586421SSepherosa Ziehau int error, mask; 8622d586421SSepherosa Ziehau 8632d586421SSepherosa Ziehau sc_if = ifp->if_softc; 8642d586421SSepherosa Ziehau ifr = (struct ifreq *)data; 8652d586421SSepherosa Ziehau error = 0; 8662d586421SSepherosa Ziehau 8672d586421SSepherosa Ziehau switch(command) { 8682d586421SSepherosa Ziehau case SIOCSIFMTU: 8692d586421SSepherosa Ziehau #ifdef MSK_JUMBO 8702d586421SSepherosa Ziehau if (ifr->ifr_mtu > MSK_JUMBO_MTU || ifr->ifr_mtu < ETHERMIN) { 8712d586421SSepherosa Ziehau error = EINVAL; 8722d586421SSepherosa Ziehau break; 8732d586421SSepherosa Ziehau } 8742d586421SSepherosa Ziehau if (sc_if->msk_softc->msk_hw_id == CHIP_ID_YUKON_FE && 8752d586421SSepherosa Ziehau ifr->ifr_mtu > MSK_MAX_FRAMELEN) { 8762d586421SSepherosa Ziehau error = EINVAL; 8772d586421SSepherosa Ziehau break; 8782d586421SSepherosa Ziehau } 8792d586421SSepherosa Ziehau ifp->if_mtu = ifr->ifr_mtu; 8802d586421SSepherosa Ziehau if ((ifp->if_flags & IFF_RUNNING) != 0) 8812d586421SSepherosa Ziehau msk_init(sc_if); 8822d586421SSepherosa Ziehau #else 8832d586421SSepherosa Ziehau error = EOPNOTSUPP; 8842d586421SSepherosa Ziehau #endif 8852d586421SSepherosa Ziehau break; 8862d586421SSepherosa Ziehau 8872d586421SSepherosa Ziehau case SIOCSIFFLAGS: 8882d586421SSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 8892d586421SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 8902d586421SSepherosa Ziehau if (((ifp->if_flags ^ sc_if->msk_if_flags) 891dc7303ffSSepherosa Ziehau & (IFF_PROMISC | IFF_ALLMULTI)) != 0) 892dc7303ffSSepherosa Ziehau msk_rxfilter(sc_if); 8932d586421SSepherosa Ziehau } else { 8942d586421SSepherosa Ziehau if (sc_if->msk_detach == 0) 8952d586421SSepherosa Ziehau msk_init(sc_if); 8962d586421SSepherosa Ziehau } 8972d586421SSepherosa Ziehau } else { 8982d586421SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 8992d586421SSepherosa Ziehau msk_stop(sc_if); 9002d586421SSepherosa Ziehau } 9012d586421SSepherosa Ziehau sc_if->msk_if_flags = ifp->if_flags; 9022d586421SSepherosa Ziehau break; 9032d586421SSepherosa Ziehau 9042d586421SSepherosa Ziehau case SIOCADDMULTI: 9052d586421SSepherosa Ziehau case SIOCDELMULTI: 9062d586421SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 907dc7303ffSSepherosa Ziehau msk_rxfilter(sc_if); 9082d586421SSepherosa Ziehau break; 9092d586421SSepherosa Ziehau 9102d586421SSepherosa Ziehau case SIOCGIFMEDIA: 9112d586421SSepherosa Ziehau case SIOCSIFMEDIA: 9122d586421SSepherosa Ziehau mii = device_get_softc(sc_if->msk_miibus); 9132d586421SSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); 9142d586421SSepherosa Ziehau break; 9152d586421SSepherosa Ziehau 9162d586421SSepherosa Ziehau case SIOCSIFCAP: 9172d586421SSepherosa Ziehau mask = ifr->ifr_reqcap ^ ifp->if_capenable; 9182d586421SSepherosa Ziehau if ((mask & IFCAP_TXCSUM) != 0) { 9192d586421SSepherosa Ziehau ifp->if_capenable ^= IFCAP_TXCSUM; 9202d586421SSepherosa Ziehau if ((IFCAP_TXCSUM & ifp->if_capenable) != 0 && 9212d586421SSepherosa Ziehau (IFCAP_TXCSUM & ifp->if_capabilities) != 0) 9222d586421SSepherosa Ziehau ifp->if_hwassist |= MSK_CSUM_FEATURES; 9232d586421SSepherosa Ziehau else 9242d586421SSepherosa Ziehau ifp->if_hwassist &= ~MSK_CSUM_FEATURES; 9252d586421SSepherosa Ziehau } 9262d586421SSepherosa Ziehau #ifdef notyet 9272d586421SSepherosa Ziehau if ((mask & IFCAP_VLAN_HWTAGGING) != 0) { 9282d586421SSepherosa Ziehau ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 9292d586421SSepherosa Ziehau msk_setvlan(sc_if, ifp); 9302d586421SSepherosa Ziehau } 9312d586421SSepherosa Ziehau #endif 9322d586421SSepherosa Ziehau 9332d586421SSepherosa Ziehau if (sc_if->msk_framesize > MSK_MAX_FRAMELEN && 9342d586421SSepherosa Ziehau sc_if->msk_softc->msk_hw_id == CHIP_ID_YUKON_EC_U) { 9352d586421SSepherosa Ziehau /* 9362d586421SSepherosa Ziehau * In Yukon EC Ultra, TSO & checksum offload is not 9372d586421SSepherosa Ziehau * supported for jumbo frame. 9382d586421SSepherosa Ziehau */ 9392d586421SSepherosa Ziehau ifp->if_hwassist &= ~MSK_CSUM_FEATURES; 9402d586421SSepherosa Ziehau ifp->if_capenable &= ~IFCAP_TXCSUM; 9412d586421SSepherosa Ziehau } 9422d586421SSepherosa Ziehau break; 9432d586421SSepherosa Ziehau 9442d586421SSepherosa Ziehau default: 9452d586421SSepherosa Ziehau error = ether_ioctl(ifp, command, data); 9462d586421SSepherosa Ziehau break; 9472d586421SSepherosa Ziehau } 9482d586421SSepherosa Ziehau 9492d586421SSepherosa Ziehau return (error); 9502d586421SSepherosa Ziehau } 9512d586421SSepherosa Ziehau 9522d586421SSepherosa Ziehau static int 9532d586421SSepherosa Ziehau mskc_probe(device_t dev) 9542d586421SSepherosa Ziehau { 9552d586421SSepherosa Ziehau const struct msk_product *mp; 9562d586421SSepherosa Ziehau uint16_t vendor, devid; 9572d586421SSepherosa Ziehau 9582d586421SSepherosa Ziehau vendor = pci_get_vendor(dev); 9592d586421SSepherosa Ziehau devid = pci_get_device(dev); 9602d586421SSepherosa Ziehau for (mp = msk_products; mp->msk_name != NULL; ++mp) { 9612d586421SSepherosa Ziehau if (vendor == mp->msk_vendorid && devid == mp->msk_deviceid) { 9622d586421SSepherosa Ziehau device_set_desc(dev, mp->msk_name); 9632d586421SSepherosa Ziehau return (0); 9642d586421SSepherosa Ziehau } 9652d586421SSepherosa Ziehau } 9662d586421SSepherosa Ziehau return (ENXIO); 9672d586421SSepherosa Ziehau } 9682d586421SSepherosa Ziehau 9692d586421SSepherosa Ziehau static int 9702d586421SSepherosa Ziehau mskc_setup_rambuffer(struct msk_softc *sc) 9712d586421SSepherosa Ziehau { 9722d586421SSepherosa Ziehau int next; 9732d586421SSepherosa Ziehau int i; 9742d586421SSepherosa Ziehau 9752d586421SSepherosa Ziehau /* Get adapter SRAM size. */ 9762a9b20a4SSepherosa Ziehau sc->msk_ramsize = CSR_READ_1(sc, B2_E_0) * 4; 9772d586421SSepherosa Ziehau if (bootverbose) { 9782d586421SSepherosa Ziehau device_printf(sc->msk_dev, 9792d586421SSepherosa Ziehau "RAM buffer size : %dKB\n", sc->msk_ramsize); 9802d586421SSepherosa Ziehau } 9812a9b20a4SSepherosa Ziehau if (sc->msk_ramsize == 0) 9822a9b20a4SSepherosa Ziehau return (0); 9832a9b20a4SSepherosa Ziehau sc->msk_pflags |= MSK_FLAG_RAMBUF; 9842a9b20a4SSepherosa Ziehau 9852d586421SSepherosa Ziehau /* 9862d586421SSepherosa Ziehau * Give receiver 2/3 of memory and round down to the multiple 9872d586421SSepherosa Ziehau * of 1024. Tx/Rx RAM buffer size of Yukon II shoud be multiple 9882d586421SSepherosa Ziehau * of 1024. 9892d586421SSepherosa Ziehau */ 9902d586421SSepherosa Ziehau sc->msk_rxqsize = rounddown((sc->msk_ramsize * 1024 * 2) / 3, 1024); 9912d586421SSepherosa Ziehau sc->msk_txqsize = (sc->msk_ramsize * 1024) - sc->msk_rxqsize; 9922d586421SSepherosa Ziehau for (i = 0, next = 0; i < sc->msk_num_port; i++) { 9932d586421SSepherosa Ziehau sc->msk_rxqstart[i] = next; 9942d586421SSepherosa Ziehau sc->msk_rxqend[i] = next + sc->msk_rxqsize - 1; 9952d586421SSepherosa Ziehau next = sc->msk_rxqend[i] + 1; 9962d586421SSepherosa Ziehau sc->msk_txqstart[i] = next; 9972d586421SSepherosa Ziehau sc->msk_txqend[i] = next + sc->msk_txqsize - 1; 9982d586421SSepherosa Ziehau next = sc->msk_txqend[i] + 1; 9992d586421SSepherosa Ziehau if (bootverbose) { 10002d586421SSepherosa Ziehau device_printf(sc->msk_dev, 10012d586421SSepherosa Ziehau "Port %d : Rx Queue %dKB(0x%08x:0x%08x)\n", i, 10022d586421SSepherosa Ziehau sc->msk_rxqsize / 1024, sc->msk_rxqstart[i], 10032d586421SSepherosa Ziehau sc->msk_rxqend[i]); 10042d586421SSepherosa Ziehau device_printf(sc->msk_dev, 10052d586421SSepherosa Ziehau "Port %d : Tx Queue %dKB(0x%08x:0x%08x)\n", i, 10062d586421SSepherosa Ziehau sc->msk_txqsize / 1024, sc->msk_txqstart[i], 10072d586421SSepherosa Ziehau sc->msk_txqend[i]); 10082d586421SSepherosa Ziehau } 10092d586421SSepherosa Ziehau } 10102d586421SSepherosa Ziehau 10112d586421SSepherosa Ziehau return (0); 10122d586421SSepherosa Ziehau } 10132d586421SSepherosa Ziehau 10142d586421SSepherosa Ziehau static void 10152d586421SSepherosa Ziehau mskc_phy_power(struct msk_softc *sc, int mode) 10162d586421SSepherosa Ziehau { 101760ad6a1fSSepherosa Ziehau uint32_t our, val; 10182d586421SSepherosa Ziehau int i; 10192d586421SSepherosa Ziehau 10202d586421SSepherosa Ziehau switch (mode) { 10212d586421SSepherosa Ziehau case MSK_PHY_POWERUP: 10222d586421SSepherosa Ziehau /* Switch power to VCC (WA for VAUX problem). */ 10232d586421SSepherosa Ziehau CSR_WRITE_1(sc, B0_POWER_CTRL, 10242d586421SSepherosa Ziehau PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); 10252d586421SSepherosa Ziehau /* Disable Core Clock Division, set Clock Select to 0. */ 10262d586421SSepherosa Ziehau CSR_WRITE_4(sc, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS); 10272d586421SSepherosa Ziehau 10282d586421SSepherosa Ziehau val = 0; 10292d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_XL && 10302d586421SSepherosa Ziehau sc->msk_hw_rev > CHIP_REV_YU_XL_A1) { 10312d586421SSepherosa Ziehau /* Enable bits are inverted. */ 10322d586421SSepherosa Ziehau val = Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | 10332d586421SSepherosa Ziehau Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | 10342d586421SSepherosa Ziehau Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS; 10352d586421SSepherosa Ziehau } 10362d586421SSepherosa Ziehau /* 10372d586421SSepherosa Ziehau * Enable PCI & Core Clock, enable clock gating for both Links. 10382d586421SSepherosa Ziehau */ 10392d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_Y2_CLK_GATE, val); 10402d586421SSepherosa Ziehau 104160ad6a1fSSepherosa Ziehau our = CSR_PCI_READ_4(sc, PCI_OUR_REG_1); 104260ad6a1fSSepherosa Ziehau our &= ~(PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD); 1043d9e919c4SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_XL) { 1044e7e20ceeSSepherosa Ziehau if (sc->msk_hw_rev > CHIP_REV_YU_XL_A1) { 10452d586421SSepherosa Ziehau /* Deassert Low Power for 1st PHY. */ 104660ad6a1fSSepherosa Ziehau our |= PCI_Y2_PHY1_COMA; 10472d586421SSepherosa Ziehau if (sc->msk_num_port > 1) 104860ad6a1fSSepherosa Ziehau our |= PCI_Y2_PHY2_COMA; 1049e7e20ceeSSepherosa Ziehau } 1050d9e919c4SSepherosa Ziehau } 105160ad6a1fSSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_EC_U || 105260ad6a1fSSepherosa Ziehau sc->msk_hw_id == CHIP_ID_YUKON_EX || 105360ad6a1fSSepherosa Ziehau sc->msk_hw_id >= CHIP_ID_YUKON_FE_P) { 105460ad6a1fSSepherosa Ziehau val = CSR_PCI_READ_4(sc, PCI_OUR_REG_4); 105560ad6a1fSSepherosa Ziehau val &= (PCI_FORCE_ASPM_REQUEST | 105660ad6a1fSSepherosa Ziehau PCI_ASPM_GPHY_LINK_DOWN | PCI_ASPM_INT_FIFO_EMPTY | 105760ad6a1fSSepherosa Ziehau PCI_ASPM_CLKRUN_REQUEST); 10582d586421SSepherosa Ziehau /* Set all bits to 0 except bits 15..12. */ 105960ad6a1fSSepherosa Ziehau CSR_PCI_WRITE_4(sc, PCI_OUR_REG_4, val); 106060ad6a1fSSepherosa Ziehau val = CSR_PCI_READ_4(sc, PCI_OUR_REG_5); 106160ad6a1fSSepherosa Ziehau val &= PCI_CTL_TIM_VMAIN_AV_MSK; 106260ad6a1fSSepherosa Ziehau CSR_PCI_WRITE_4(sc, PCI_OUR_REG_5, val); 106321437caeSSepherosa Ziehau CSR_PCI_WRITE_4(sc, PCI_CFG_REG_1, 0); 106460ad6a1fSSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, Y2_HW_WOL_ON); 1065d9e919c4SSepherosa Ziehau /* 1066d9e919c4SSepherosa Ziehau * Disable status race, workaround for 1067d9e919c4SSepherosa Ziehau * Yukon EC Ultra & Yukon EX. 1068d9e919c4SSepherosa Ziehau */ 1069d9e919c4SSepherosa Ziehau val = CSR_READ_4(sc, B2_GP_IO); 1070d9e919c4SSepherosa Ziehau val |= GLB_GPIO_STAT_RACE_DIS; 1071d9e919c4SSepherosa Ziehau CSR_WRITE_4(sc, B2_GP_IO, val); 1072d9e919c4SSepherosa Ziehau CSR_READ_4(sc, B2_GP_IO); 10732d586421SSepherosa Ziehau } 107460ad6a1fSSepherosa Ziehau /* Release PHY from PowerDown/COMA mode. */ 107560ad6a1fSSepherosa Ziehau CSR_PCI_WRITE_4(sc, PCI_OUR_REG_1, our); 107660ad6a1fSSepherosa Ziehau 10772d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; i++) { 10782d586421SSepherosa Ziehau CSR_WRITE_2(sc, MR_ADDR(i, GMAC_LINK_CTRL), 10792d586421SSepherosa Ziehau GMLC_RST_SET); 10802d586421SSepherosa Ziehau CSR_WRITE_2(sc, MR_ADDR(i, GMAC_LINK_CTRL), 10812d586421SSepherosa Ziehau GMLC_RST_CLR); 10822d586421SSepherosa Ziehau } 10832d586421SSepherosa Ziehau break; 10842d586421SSepherosa Ziehau case MSK_PHY_POWERDOWN: 108521437caeSSepherosa Ziehau val = CSR_PCI_READ_4(sc, PCI_OUR_REG_1); 10862d586421SSepherosa Ziehau val |= PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD; 10872d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_XL && 10882d586421SSepherosa Ziehau sc->msk_hw_rev > CHIP_REV_YU_XL_A1) { 10892d586421SSepherosa Ziehau val &= ~PCI_Y2_PHY1_COMA; 10902d586421SSepherosa Ziehau if (sc->msk_num_port > 1) 10912d586421SSepherosa Ziehau val &= ~PCI_Y2_PHY2_COMA; 10922d586421SSepherosa Ziehau } 109321437caeSSepherosa Ziehau CSR_PCI_WRITE_4(sc, PCI_OUR_REG_1, val); 10942d586421SSepherosa Ziehau 10952d586421SSepherosa Ziehau val = Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS | 10962d586421SSepherosa Ziehau Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS | 10972d586421SSepherosa Ziehau Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS; 10982d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_XL && 10992d586421SSepherosa Ziehau sc->msk_hw_rev > CHIP_REV_YU_XL_A1) { 11002d586421SSepherosa Ziehau /* Enable bits are inverted. */ 11012d586421SSepherosa Ziehau val = 0; 11022d586421SSepherosa Ziehau } 11032d586421SSepherosa Ziehau /* 11042d586421SSepherosa Ziehau * Disable PCI & Core Clock, disable clock gating for 11052d586421SSepherosa Ziehau * both Links. 11062d586421SSepherosa Ziehau */ 11072d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_Y2_CLK_GATE, val); 11082d586421SSepherosa Ziehau CSR_WRITE_1(sc, B0_POWER_CTRL, 11092d586421SSepherosa Ziehau PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF); 11102d586421SSepherosa Ziehau break; 11112d586421SSepherosa Ziehau default: 11122d586421SSepherosa Ziehau break; 11132d586421SSepherosa Ziehau } 11142d586421SSepherosa Ziehau } 11152d586421SSepherosa Ziehau 11162d586421SSepherosa Ziehau static void 11172d586421SSepherosa Ziehau mskc_reset(struct msk_softc *sc) 11182d586421SSepherosa Ziehau { 11192d586421SSepherosa Ziehau bus_addr_t addr; 11202d586421SSepherosa Ziehau uint16_t status; 11212d586421SSepherosa Ziehau uint32_t val; 11222d586421SSepherosa Ziehau int i; 11232d586421SSepherosa Ziehau 11242d586421SSepherosa Ziehau /* Disable ASF. */ 112539f451b4SSepherosa Ziehau if (sc->msk_hw_id >= CHIP_ID_YUKON_XL && 112639f451b4SSepherosa Ziehau sc->msk_hw_id <= CHIP_ID_YUKON_SUPR) { 112739f451b4SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_EX || 112839f451b4SSepherosa Ziehau sc->msk_hw_id == CHIP_ID_YUKON_SUPR) { 112939f451b4SSepherosa Ziehau CSR_WRITE_4(sc, B28_Y2_CPU_WDOG, 0); 1130d9e919c4SSepherosa Ziehau status = CSR_READ_2(sc, B28_Y2_ASF_HCU_CCSR); 1131d9e919c4SSepherosa Ziehau /* Clear AHB bridge & microcontroller reset. */ 1132d9e919c4SSepherosa Ziehau status &= ~(Y2_ASF_HCU_CCSR_AHB_RST | 1133d9e919c4SSepherosa Ziehau Y2_ASF_HCU_CCSR_CPU_RST_MODE); 1134d9e919c4SSepherosa Ziehau /* Clear ASF microcontroller state. */ 1135d9e919c4SSepherosa Ziehau status &= ~Y2_ASF_HCU_CCSR_UC_STATE_MSK; 113639f451b4SSepherosa Ziehau status &= ~Y2_ASF_HCU_CCSR_CPU_CLK_DIVIDE_MSK; 1137d9e919c4SSepherosa Ziehau CSR_WRITE_2(sc, B28_Y2_ASF_HCU_CCSR, status); 113839f451b4SSepherosa Ziehau CSR_WRITE_4(sc, B28_Y2_CPU_WDOG, 0); 1139d9e919c4SSepherosa Ziehau } else { 1140d9e919c4SSepherosa Ziehau CSR_WRITE_1(sc, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET); 11412d586421SSepherosa Ziehau } 1142d9e919c4SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, Y2_ASF_DISABLE); 11432d586421SSepherosa Ziehau /* 114439f451b4SSepherosa Ziehau * Since we disabled ASF, S/W reset is required for 114539f451b4SSepherosa Ziehau * Power Management. 11462d586421SSepherosa Ziehau */ 11472d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_SET); 11482d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR); 114939f451b4SSepherosa Ziehau } 11502d586421SSepherosa Ziehau 11512d586421SSepherosa Ziehau /* Clear all error bits in the PCI status register. */ 11522d586421SSepherosa Ziehau status = pci_read_config(sc->msk_dev, PCIR_STATUS, 2); 11532d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_ON); 11542d586421SSepherosa Ziehau 11552d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, PCIR_STATUS, status | 11562d586421SSepherosa Ziehau PCIM_STATUS_PERR | PCIM_STATUS_SERR | PCIM_STATUS_RMABORT | 11572d586421SSepherosa Ziehau PCIM_STATUS_RTABORT | PCIM_STATUS_PERRREPORT, 2); 11582d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_MRST_CLR); 11592d586421SSepherosa Ziehau 11602d586421SSepherosa Ziehau switch (sc->msk_bustype) { 11612d586421SSepherosa Ziehau case MSK_PEX_BUS: 11622d586421SSepherosa Ziehau /* Clear all PEX errors. */ 11632d586421SSepherosa Ziehau CSR_PCI_WRITE_4(sc, PEX_UNC_ERR_STAT, 0xffffffff); 11642d586421SSepherosa Ziehau val = CSR_PCI_READ_4(sc, PEX_UNC_ERR_STAT); 11652d586421SSepherosa Ziehau if ((val & PEX_RX_OV) != 0) { 11662d586421SSepherosa Ziehau sc->msk_intrmask &= ~Y2_IS_HW_ERR; 11672d586421SSepherosa Ziehau sc->msk_intrhwemask &= ~Y2_IS_PCI_EXP; 11682d586421SSepherosa Ziehau } 11692d586421SSepherosa Ziehau break; 11702d586421SSepherosa Ziehau case MSK_PCI_BUS: 11712d586421SSepherosa Ziehau case MSK_PCIX_BUS: 11722d586421SSepherosa Ziehau /* Set Cache Line Size to 2(8bytes) if configured to 0. */ 11732d586421SSepherosa Ziehau val = pci_read_config(sc->msk_dev, PCIR_CACHELNSZ, 1); 11742d586421SSepherosa Ziehau if (val == 0) 11752d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, PCIR_CACHELNSZ, 2, 1); 11762d586421SSepherosa Ziehau if (sc->msk_bustype == MSK_PCIX_BUS) { 11772d586421SSepherosa Ziehau /* Set Cache Line Size opt. */ 117821437caeSSepherosa Ziehau val = CSR_PCI_READ_4(sc, PCI_OUR_REG_1); 11792d586421SSepherosa Ziehau val |= PCI_CLS_OPT; 118021437caeSSepherosa Ziehau CSR_PCI_WRITE_4(sc, PCI_OUR_REG_1, val); 11812d586421SSepherosa Ziehau } 11822d586421SSepherosa Ziehau break; 11832d586421SSepherosa Ziehau } 11842d586421SSepherosa Ziehau /* Set PHY power state. */ 11852d586421SSepherosa Ziehau mskc_phy_power(sc, MSK_PHY_POWERUP); 11862d586421SSepherosa Ziehau 11872d586421SSepherosa Ziehau /* Reset GPHY/GMAC Control */ 11882d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; i++) { 11892d586421SSepherosa Ziehau /* GPHY Control reset. */ 119086d08fa7SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(i, GPHY_CTRL), GPC_RST_SET); 119186d08fa7SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(i, GPHY_CTRL), GPC_RST_CLR); 11922d586421SSepherosa Ziehau /* GMAC Control reset. */ 11932d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), GMC_RST_SET); 11942d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), GMC_RST_CLR); 11952d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), GMC_F_LOOPB_OFF); 11960d557164SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_EX || 11970d557164SSepherosa Ziehau sc->msk_hw_id == CHIP_ID_YUKON_SUPR) { 1198d9e919c4SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(i, GMAC_CTRL), 1199d9e919c4SSepherosa Ziehau GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON | 1200d9e919c4SSepherosa Ziehau GMC_BYP_RETR_ON); 1201d9e919c4SSepherosa Ziehau } 12022d586421SSepherosa Ziehau } 12030d557164SSepherosa Ziehau 12040d557164SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_SUPR && 12050d557164SSepherosa Ziehau sc->msk_hw_rev > CHIP_REV_YU_SU_B0) 12060d557164SSepherosa Ziehau CSR_PCI_WRITE_4(sc, PCI_OUR_REG_3, PCI_CLK_MACSEC_DIS); 12078e916b42SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_OPT && sc->msk_hw_rev == 0) { 12088e916b42SSepherosa Ziehau /* Disable PCIe PHY powerdown(reg 0x80, bit7). */ 12098e916b42SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PEX_PHY_DATA, (0x0080 << 16) | 0x0080); 12108e916b42SSepherosa Ziehau } 12112d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_OFF); 12122d586421SSepherosa Ziehau 12132d586421SSepherosa Ziehau /* LED On. */ 12142d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, Y2_LED_STAT_ON); 12152d586421SSepherosa Ziehau 12162d586421SSepherosa Ziehau /* Clear TWSI IRQ. */ 12172d586421SSepherosa Ziehau CSR_WRITE_4(sc, B2_I2C_IRQ, I2C_CLR_IRQ); 12182d586421SSepherosa Ziehau 12192d586421SSepherosa Ziehau /* Turn off hardware timer. */ 12202d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TI_CTRL, TIM_STOP); 12212d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TI_CTRL, TIM_CLR_IRQ); 12222d586421SSepherosa Ziehau 12232d586421SSepherosa Ziehau /* Turn off descriptor polling. */ 12242d586421SSepherosa Ziehau CSR_WRITE_1(sc, B28_DPT_CTRL, DPT_STOP); 12252d586421SSepherosa Ziehau 12262d586421SSepherosa Ziehau /* Turn off time stamps. */ 12272d586421SSepherosa Ziehau CSR_WRITE_1(sc, GMAC_TI_ST_CTRL, GMT_ST_STOP); 12282d586421SSepherosa Ziehau CSR_WRITE_1(sc, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ); 12292d586421SSepherosa Ziehau 123002eb431eSSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_XL || 123102eb431eSSepherosa Ziehau sc->msk_hw_id == CHIP_ID_YUKON_EC || 123202eb431eSSepherosa Ziehau sc->msk_hw_id == CHIP_ID_YUKON_FE) { 12332d586421SSepherosa Ziehau /* Configure timeout values. */ 12342d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; i++) { 123502eb431eSSepherosa Ziehau CSR_WRITE_2(sc, SELECT_RAM_BUFFER(i, B3_RI_CTRL), 123602eb431eSSepherosa Ziehau RI_RST_SET); 123702eb431eSSepherosa Ziehau CSR_WRITE_2(sc, SELECT_RAM_BUFFER(i, B3_RI_CTRL), 123802eb431eSSepherosa Ziehau RI_RST_CLR); 12392d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_WTO_R1), 12402d586421SSepherosa Ziehau MSK_RI_TO_53); 12412d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_WTO_XA1), 12422d586421SSepherosa Ziehau MSK_RI_TO_53); 12432d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_WTO_XS1), 12442d586421SSepherosa Ziehau MSK_RI_TO_53); 12452d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_RTO_R1), 12462d586421SSepherosa Ziehau MSK_RI_TO_53); 12472d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_RTO_XA1), 12482d586421SSepherosa Ziehau MSK_RI_TO_53); 12492d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_RTO_XS1), 12502d586421SSepherosa Ziehau MSK_RI_TO_53); 12512d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_WTO_R2), 12522d586421SSepherosa Ziehau MSK_RI_TO_53); 12532d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_WTO_XA2), 12542d586421SSepherosa Ziehau MSK_RI_TO_53); 12552d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_WTO_XS2), 12562d586421SSepherosa Ziehau MSK_RI_TO_53); 12572d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_RTO_R2), 12582d586421SSepherosa Ziehau MSK_RI_TO_53); 12592d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_RTO_XA2), 12602d586421SSepherosa Ziehau MSK_RI_TO_53); 12612d586421SSepherosa Ziehau CSR_WRITE_1(sc, SELECT_RAM_BUFFER(i, B3_RI_RTO_XS2), 12622d586421SSepherosa Ziehau MSK_RI_TO_53); 12632d586421SSepherosa Ziehau } 126402eb431eSSepherosa Ziehau } 12652d586421SSepherosa Ziehau 12662d586421SSepherosa Ziehau /* Disable all interrupts. */ 12672d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_HWE_IMSK, 0); 12682d586421SSepherosa Ziehau CSR_READ_4(sc, B0_HWE_IMSK); 12692d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, 0); 12702d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 12712d586421SSepherosa Ziehau 12722d586421SSepherosa Ziehau /* 12732d586421SSepherosa Ziehau * On dual port PCI-X card, there is an problem where status 12742d586421SSepherosa Ziehau * can be received out of order due to split transactions. 12752d586421SSepherosa Ziehau */ 127678c8aca9SSepherosa Ziehau if (sc->msk_pcixcap != 0 && sc->msk_num_port > 1) { 12772d586421SSepherosa Ziehau uint16_t pcix_cmd; 12782d586421SSepherosa Ziehau 127978c8aca9SSepherosa Ziehau pcix_cmd = pci_read_config(sc->msk_dev, 128078c8aca9SSepherosa Ziehau sc->msk_pcixcap + PCIXR_COMMAND, 2); 12812d586421SSepherosa Ziehau /* Clear Max Outstanding Split Transactions. */ 128278c8aca9SSepherosa Ziehau pcix_cmd &= ~PCIXM_COMMAND_MAX_SPLITS; 12832d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_ON); 128478c8aca9SSepherosa Ziehau pci_write_config(sc->msk_dev, 128578c8aca9SSepherosa Ziehau sc->msk_pcixcap + PCIXR_COMMAND, pcix_cmd, 2); 12862d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_OFF); 12872d586421SSepherosa Ziehau } 128878c8aca9SSepherosa Ziehau if (sc->msk_pciecap != 0) { 128978c8aca9SSepherosa Ziehau /* Change Max. Read Request Size to 2048 bytes. */ 129078c8aca9SSepherosa Ziehau if (pcie_get_max_readrq(sc->msk_dev) == 129178c8aca9SSepherosa Ziehau PCIEM_DEVCTL_MAX_READRQ_512) { 129278c8aca9SSepherosa Ziehau pcie_set_max_readrq(sc->msk_dev, 129378c8aca9SSepherosa Ziehau PCIEM_DEVCTL_MAX_READRQ_2048); 12942d586421SSepherosa Ziehau } 12952d586421SSepherosa Ziehau } 12962d586421SSepherosa Ziehau 12972d586421SSepherosa Ziehau /* Clear status list. */ 12982d586421SSepherosa Ziehau bzero(sc->msk_stat_ring, 12992d586421SSepherosa Ziehau sizeof(struct msk_stat_desc) * MSK_STAT_RING_CNT); 13002d586421SSepherosa Ziehau sc->msk_stat_cons = 0; 13012d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_RST_SET); 13022d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_RST_CLR); 13032d586421SSepherosa Ziehau /* Set the status list base address. */ 13042d586421SSepherosa Ziehau addr = sc->msk_stat_ring_paddr; 13052d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_LIST_ADDR_LO, MSK_ADDR_LO(addr)); 13062d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_LIST_ADDR_HI, MSK_ADDR_HI(addr)); 13072d586421SSepherosa Ziehau /* Set the status list last index. */ 13082d586421SSepherosa Ziehau CSR_WRITE_2(sc, STAT_LAST_IDX, MSK_STAT_RING_CNT - 1); 13092d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_EC && 13102d586421SSepherosa Ziehau sc->msk_hw_rev == CHIP_REV_YU_EC_A1) { 13112d586421SSepherosa Ziehau /* WA for dev. #4.3 */ 13122d586421SSepherosa Ziehau CSR_WRITE_2(sc, STAT_TX_IDX_TH, ST_TXTH_IDX_MASK); 13132d586421SSepherosa Ziehau /* WA for dev. #4.18 */ 13142d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_FIFO_WM, 0x21); 13152d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_FIFO_ISR_WM, 0x07); 13162d586421SSepherosa Ziehau } else { 13172d586421SSepherosa Ziehau CSR_WRITE_2(sc, STAT_TX_IDX_TH, 0x0a); 13182d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_FIFO_WM, 0x10); 13192d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_XL && 13202d586421SSepherosa Ziehau sc->msk_hw_rev == CHIP_REV_YU_XL_A0) 13212d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_FIFO_ISR_WM, 0x04); 13222d586421SSepherosa Ziehau else 13232d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_FIFO_ISR_WM, 0x10); 13242d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_ISR_TIMER_INI, 0x0190); 13252d586421SSepherosa Ziehau } 13262d586421SSepherosa Ziehau /* 13272d586421SSepherosa Ziehau * Use default value for STAT_ISR_TIMER_INI, STAT_LEV_TIMER_INI. 13282d586421SSepherosa Ziehau */ 13292d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_TX_TIMER_INI, MSK_USECS(sc, 1000)); 13302d586421SSepherosa Ziehau 13312d586421SSepherosa Ziehau /* Enable status unit. */ 13322d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_OP_ON); 13332d586421SSepherosa Ziehau 13342d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_TX_TIMER_CTRL, TIM_START); 13352d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_LEV_TIMER_CTRL, TIM_START); 13362d586421SSepherosa Ziehau CSR_WRITE_1(sc, STAT_ISR_TIMER_CTRL, TIM_START); 13372d586421SSepherosa Ziehau } 13382d586421SSepherosa Ziehau 13392d586421SSepherosa Ziehau static int 13402d586421SSepherosa Ziehau msk_probe(device_t dev) 13412d586421SSepherosa Ziehau { 13422d586421SSepherosa Ziehau struct msk_softc *sc = device_get_softc(device_get_parent(dev)); 13432d586421SSepherosa Ziehau char desc[100]; 13442d586421SSepherosa Ziehau 13452d586421SSepherosa Ziehau /* 13462d586421SSepherosa Ziehau * Not much to do here. We always know there will be 13472d586421SSepherosa Ziehau * at least one GMAC present, and if there are two, 13482d586421SSepherosa Ziehau * mskc_attach() will create a second device instance 13492d586421SSepherosa Ziehau * for us. 13502d586421SSepherosa Ziehau */ 13512d586421SSepherosa Ziehau ksnprintf(desc, sizeof(desc), 13522d586421SSepherosa Ziehau "Marvell Technology Group Ltd. %s Id 0x%02x Rev 0x%02x", 13532d586421SSepherosa Ziehau model_name[sc->msk_hw_id - CHIP_ID_YUKON_XL], sc->msk_hw_id, 13542d586421SSepherosa Ziehau sc->msk_hw_rev); 13552d586421SSepherosa Ziehau device_set_desc_copy(dev, desc); 13562d586421SSepherosa Ziehau 13572d586421SSepherosa Ziehau return (0); 13582d586421SSepherosa Ziehau } 13592d586421SSepherosa Ziehau 13602d586421SSepherosa Ziehau static int 13612d586421SSepherosa Ziehau msk_attach(device_t dev) 13622d586421SSepherosa Ziehau { 13632d586421SSepherosa Ziehau struct msk_softc *sc = device_get_softc(device_get_parent(dev)); 13642d586421SSepherosa Ziehau struct msk_if_softc *sc_if = device_get_softc(dev); 13652d586421SSepherosa Ziehau struct ifnet *ifp = &sc_if->arpcom.ac_if; 13662d586421SSepherosa Ziehau int i, port, error; 13672d586421SSepherosa Ziehau uint8_t eaddr[ETHER_ADDR_LEN]; 13682d586421SSepherosa Ziehau 13692d586421SSepherosa Ziehau port = *(int *)device_get_ivars(dev); 13702d586421SSepherosa Ziehau KKASSERT(port == MSK_PORT_A || port == MSK_PORT_B); 13712d586421SSepherosa Ziehau 13722d586421SSepherosa Ziehau kfree(device_get_ivars(dev), M_DEVBUF); 13732d586421SSepherosa Ziehau device_set_ivars(dev, NULL); 13742d586421SSepherosa Ziehau 13752d586421SSepherosa Ziehau callout_init(&sc_if->msk_tick_ch); 13762d586421SSepherosa Ziehau if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 13772d586421SSepherosa Ziehau 13782d586421SSepherosa Ziehau sc_if->msk_if_dev = dev; 13792d586421SSepherosa Ziehau sc_if->msk_port = port; 13802d586421SSepherosa Ziehau sc_if->msk_softc = sc; 13812d586421SSepherosa Ziehau sc_if->msk_ifp = ifp; 13822a9b20a4SSepherosa Ziehau sc_if->msk_flags = sc->msk_pflags; 13832d586421SSepherosa Ziehau sc->msk_if[port] = sc_if; 13842d586421SSepherosa Ziehau 13852d586421SSepherosa Ziehau /* Setup Tx/Rx queue register offsets. */ 13862d586421SSepherosa Ziehau if (port == MSK_PORT_A) { 13872d586421SSepherosa Ziehau sc_if->msk_txq = Q_XA1; 13882d586421SSepherosa Ziehau sc_if->msk_txsq = Q_XS1; 13892d586421SSepherosa Ziehau sc_if->msk_rxq = Q_R1; 13902d586421SSepherosa Ziehau } else { 13912d586421SSepherosa Ziehau sc_if->msk_txq = Q_XA2; 13922d586421SSepherosa Ziehau sc_if->msk_txsq = Q_XS2; 13932d586421SSepherosa Ziehau sc_if->msk_rxq = Q_R2; 13942d586421SSepherosa Ziehau } 13952d586421SSepherosa Ziehau 13962d586421SSepherosa Ziehau error = msk_txrx_dma_alloc(sc_if); 13972d586421SSepherosa Ziehau if (error) 13982d586421SSepherosa Ziehau goto fail; 13992d586421SSepherosa Ziehau 14002d586421SSepherosa Ziehau ifp->if_softc = sc_if; 14012d586421SSepherosa Ziehau ifp->if_mtu = ETHERMTU; 14022d586421SSepherosa Ziehau ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 14032d586421SSepherosa Ziehau ifp->if_init = msk_init; 14042d586421SSepherosa Ziehau ifp->if_ioctl = msk_ioctl; 14052d586421SSepherosa Ziehau ifp->if_start = msk_start; 14062d586421SSepherosa Ziehau ifp->if_watchdog = msk_watchdog; 14072d586421SSepherosa Ziehau ifq_set_maxlen(&ifp->if_snd, MSK_TX_RING_CNT - 1); 14082d586421SSepherosa Ziehau ifq_set_ready(&ifp->if_snd); 14092d586421SSepherosa Ziehau 14102d586421SSepherosa Ziehau #ifdef notyet 14112d586421SSepherosa Ziehau /* 14122d586421SSepherosa Ziehau * IFCAP_RXCSUM capability is intentionally disabled as the hardware 14132d586421SSepherosa Ziehau * has serious bug in Rx checksum offload for all Yukon II family 14142d586421SSepherosa Ziehau * hardware. It seems there is a workaround to make it work somtimes. 14152d586421SSepherosa Ziehau * However, the workaround also have to check OP code sequences to 14162d586421SSepherosa Ziehau * verify whether the OP code is correct. Sometimes it should compute 14172d586421SSepherosa Ziehau * IP/TCP/UDP checksum in driver in order to verify correctness of 14182d586421SSepherosa Ziehau * checksum computed by hardware. If you have to compute checksum 14192d586421SSepherosa Ziehau * with software to verify the hardware's checksum why have hardware 14202d586421SSepherosa Ziehau * compute the checksum? I think there is no reason to spend time to 14212d586421SSepherosa Ziehau * make Rx checksum offload work on Yukon II hardware. 14222d586421SSepherosa Ziehau */ 14232d586421SSepherosa Ziehau ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_VLAN_MTU | 14242d586421SSepherosa Ziehau IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM; 14252d586421SSepherosa Ziehau ifp->if_hwassist = MSK_CSUM_FEATURES; 14262d586421SSepherosa Ziehau ifp->if_capenable = ifp->if_capabilities; 14272d586421SSepherosa Ziehau #endif 14282d586421SSepherosa Ziehau 14292d586421SSepherosa Ziehau /* 14302d586421SSepherosa Ziehau * Get station address for this interface. Note that 14312d586421SSepherosa Ziehau * dual port cards actually come with three station 14322d586421SSepherosa Ziehau * addresses: one for each port, plus an extra. The 14332d586421SSepherosa Ziehau * extra one is used by the SysKonnect driver software 14342d586421SSepherosa Ziehau * as a 'virtual' station address for when both ports 14352d586421SSepherosa Ziehau * are operating in failover mode. Currently we don't 14362d586421SSepherosa Ziehau * use this extra address. 14372d586421SSepherosa Ziehau */ 14382d586421SSepherosa Ziehau for (i = 0; i < ETHER_ADDR_LEN; i++) 14392d586421SSepherosa Ziehau eaddr[i] = CSR_READ_1(sc, B2_MAC_1 + (port * 8) + i); 14402d586421SSepherosa Ziehau 14412d586421SSepherosa Ziehau sc_if->msk_framesize = ifp->if_mtu + ETHER_HDR_LEN + EVL_ENCAPLEN; 14422d586421SSepherosa Ziehau 14432d586421SSepherosa Ziehau /* 14442d586421SSepherosa Ziehau * Do miibus setup. 14452d586421SSepherosa Ziehau */ 14462d586421SSepherosa Ziehau error = mii_phy_probe(dev, &sc_if->msk_miibus, 14472d586421SSepherosa Ziehau msk_mediachange, msk_mediastatus); 14482d586421SSepherosa Ziehau if (error) { 14492d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "no PHY found!\n"); 14502d586421SSepherosa Ziehau goto fail; 14512d586421SSepherosa Ziehau } 14522d586421SSepherosa Ziehau 14532d586421SSepherosa Ziehau /* 14542d586421SSepherosa Ziehau * Call MI attach routine. Can't hold locks when calling into ether_*. 14552d586421SSepherosa Ziehau */ 14562d586421SSepherosa Ziehau ether_ifattach(ifp, eaddr, &sc->msk_serializer); 14572d586421SSepherosa Ziehau #if 0 14582d586421SSepherosa Ziehau /* 14592d586421SSepherosa Ziehau * Tell the upper layer(s) we support long frames. 14602d586421SSepherosa Ziehau * Must appear after the call to ether_ifattach() because 14612d586421SSepherosa Ziehau * ether_ifattach() sets ifi_hdrlen to the default value. 14622d586421SSepherosa Ziehau */ 14632d586421SSepherosa Ziehau ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 14642d586421SSepherosa Ziehau #endif 14652d586421SSepherosa Ziehau 14662d586421SSepherosa Ziehau return 0; 14672d586421SSepherosa Ziehau fail: 14682d586421SSepherosa Ziehau msk_detach(dev); 14692d586421SSepherosa Ziehau sc->msk_if[port] = NULL; 14702d586421SSepherosa Ziehau return (error); 14712d586421SSepherosa Ziehau } 14722d586421SSepherosa Ziehau 14732d586421SSepherosa Ziehau /* 14742d586421SSepherosa Ziehau * Attach the interface. Allocate softc structures, do ifmedia 14752d586421SSepherosa Ziehau * setup and ethernet/BPF attach. 14762d586421SSepherosa Ziehau */ 14772d586421SSepherosa Ziehau static int 14782d586421SSepherosa Ziehau mskc_attach(device_t dev) 14792d586421SSepherosa Ziehau { 14802d586421SSepherosa Ziehau struct msk_softc *sc; 14819db4b353SSepherosa Ziehau int error, *port, cpuid; 14822d586421SSepherosa Ziehau 14832d586421SSepherosa Ziehau sc = device_get_softc(dev); 14842d586421SSepherosa Ziehau sc->msk_dev = dev; 14852d586421SSepherosa Ziehau lwkt_serialize_init(&sc->msk_serializer); 14862d586421SSepherosa Ziehau 1487f59f1081SSepherosa Ziehau /* 1488f59f1081SSepherosa Ziehau * Initailize sysctl variables 1489f59f1081SSepherosa Ziehau */ 1490f59f1081SSepherosa Ziehau sc->msk_process_limit = mskc_process_limit; 1491f59f1081SSepherosa Ziehau sc->msk_intr_rate = mskc_intr_rate; 1492f59f1081SSepherosa Ziehau 14932d586421SSepherosa Ziehau #ifndef BURN_BRIDGES 14942d586421SSepherosa Ziehau /* 14952d586421SSepherosa Ziehau * Handle power management nonsense. 14962d586421SSepherosa Ziehau */ 14972d586421SSepherosa Ziehau if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 14982d586421SSepherosa Ziehau uint32_t irq, bar0, bar1; 14992d586421SSepherosa Ziehau 15002d586421SSepherosa Ziehau /* Save important PCI config data. */ 15012d586421SSepherosa Ziehau bar0 = pci_read_config(dev, PCIR_BAR(0), 4); 15022d586421SSepherosa Ziehau bar1 = pci_read_config(dev, PCIR_BAR(1), 4); 15032d586421SSepherosa Ziehau irq = pci_read_config(dev, PCIR_INTLINE, 4); 15042d586421SSepherosa Ziehau 15052d586421SSepherosa Ziehau /* Reset the power state. */ 15062d586421SSepherosa Ziehau device_printf(dev, "chip is in D%d power mode " 15072d586421SSepherosa Ziehau "-- setting to D0\n", pci_get_powerstate(dev)); 15082d586421SSepherosa Ziehau 15092d586421SSepherosa Ziehau pci_set_powerstate(dev, PCI_POWERSTATE_D0); 15102d586421SSepherosa Ziehau 15112d586421SSepherosa Ziehau /* Restore PCI config data. */ 15122d586421SSepherosa Ziehau pci_write_config(dev, PCIR_BAR(0), bar0, 4); 15132d586421SSepherosa Ziehau pci_write_config(dev, PCIR_BAR(1), bar1, 4); 15142d586421SSepherosa Ziehau pci_write_config(dev, PCIR_INTLINE, irq, 4); 15152d586421SSepherosa Ziehau } 15162d586421SSepherosa Ziehau #endif /* BURN_BRIDGES */ 15172d586421SSepherosa Ziehau 15182d586421SSepherosa Ziehau /* 15192d586421SSepherosa Ziehau * Map control/status registers. 15202d586421SSepherosa Ziehau */ 15212d586421SSepherosa Ziehau pci_enable_busmaster(dev); 15222d586421SSepherosa Ziehau 15232d586421SSepherosa Ziehau /* 15242d586421SSepherosa Ziehau * Allocate I/O resource 15252d586421SSepherosa Ziehau */ 15262d586421SSepherosa Ziehau #ifdef MSK_USEIOSPACE 15272d586421SSepherosa Ziehau sc->msk_res_type = SYS_RES_IOPORT; 15282d586421SSepherosa Ziehau sc->msk_res_rid = PCIR_BAR(1); 15292d586421SSepherosa Ziehau #else 15302d586421SSepherosa Ziehau sc->msk_res_type = SYS_RES_MEMORY; 15312d586421SSepherosa Ziehau sc->msk_res_rid = PCIR_BAR(0); 15322d586421SSepherosa Ziehau #endif 15332d586421SSepherosa Ziehau sc->msk_res = bus_alloc_resource_any(dev, sc->msk_res_type, 15342d586421SSepherosa Ziehau &sc->msk_res_rid, RF_ACTIVE); 15352d586421SSepherosa Ziehau if (sc->msk_res == NULL) { 15362d586421SSepherosa Ziehau if (sc->msk_res_type == SYS_RES_MEMORY) { 15372d586421SSepherosa Ziehau sc->msk_res_type = SYS_RES_IOPORT; 15382d586421SSepherosa Ziehau sc->msk_res_rid = PCIR_BAR(1); 15392d586421SSepherosa Ziehau } else { 15402d586421SSepherosa Ziehau sc->msk_res_type = SYS_RES_MEMORY; 15412d586421SSepherosa Ziehau sc->msk_res_rid = PCIR_BAR(0); 15422d586421SSepherosa Ziehau } 15432d586421SSepherosa Ziehau sc->msk_res = bus_alloc_resource_any(dev, sc->msk_res_type, 15442d586421SSepherosa Ziehau &sc->msk_res_rid, 15452d586421SSepherosa Ziehau RF_ACTIVE); 15462d586421SSepherosa Ziehau if (sc->msk_res == NULL) { 15472d586421SSepherosa Ziehau device_printf(dev, "couldn't allocate %s resources\n", 15482d586421SSepherosa Ziehau sc->msk_res_type == SYS_RES_MEMORY ? "memory" : "I/O"); 15492d586421SSepherosa Ziehau return (ENXIO); 15502d586421SSepherosa Ziehau } 15512d586421SSepherosa Ziehau } 15522d586421SSepherosa Ziehau sc->msk_res_bt = rman_get_bustag(sc->msk_res); 15532d586421SSepherosa Ziehau sc->msk_res_bh = rman_get_bushandle(sc->msk_res); 15542d586421SSepherosa Ziehau 15552d586421SSepherosa Ziehau /* 15562d586421SSepherosa Ziehau * Allocate IRQ 15572d586421SSepherosa Ziehau */ 15582d586421SSepherosa Ziehau sc->msk_irq_rid = 0; 15592d586421SSepherosa Ziehau sc->msk_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 15602d586421SSepherosa Ziehau &sc->msk_irq_rid, 15612d586421SSepherosa Ziehau RF_SHAREABLE | RF_ACTIVE); 15622d586421SSepherosa Ziehau if (sc->msk_irq == NULL) { 15632d586421SSepherosa Ziehau device_printf(dev, "couldn't allocate IRQ resources\n"); 15642d586421SSepherosa Ziehau error = ENXIO; 15652d586421SSepherosa Ziehau goto fail; 15662d586421SSepherosa Ziehau } 15672d586421SSepherosa Ziehau 156860ad6a1fSSepherosa Ziehau /* Enable all clocks before accessing any registers. */ 156960ad6a1fSSepherosa Ziehau CSR_PCI_WRITE_4(sc, PCI_OUR_REG_3, 0); 157060ad6a1fSSepherosa Ziehau 15712d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_CLR); 15722d586421SSepherosa Ziehau sc->msk_hw_id = CSR_READ_1(sc, B2_CHIP_ID); 15732d586421SSepherosa Ziehau sc->msk_hw_rev = (CSR_READ_1(sc, B2_MAC_CFG) >> 4) & 0x0f; 15742d586421SSepherosa Ziehau /* Bail out if chip is not recognized. */ 15752d586421SSepherosa Ziehau if (sc->msk_hw_id < CHIP_ID_YUKON_XL || 15768e916b42SSepherosa Ziehau sc->msk_hw_id > CHIP_ID_YUKON_OPT || 15778e916b42SSepherosa Ziehau sc->msk_hw_id == CHIP_ID_YUKON_UNKNOWN) { 15782d586421SSepherosa Ziehau device_printf(dev, "unknown device: id=0x%02x, rev=0x%02x\n", 15792d586421SSepherosa Ziehau sc->msk_hw_id, sc->msk_hw_rev); 15802d586421SSepherosa Ziehau error = ENXIO; 15812d586421SSepherosa Ziehau goto fail; 15822d586421SSepherosa Ziehau } 15832d586421SSepherosa Ziehau 1584f59f1081SSepherosa Ziehau /* 1585f59f1081SSepherosa Ziehau * Create sysctl tree 1586f59f1081SSepherosa Ziehau */ 1587f59f1081SSepherosa Ziehau sysctl_ctx_init(&sc->msk_sysctl_ctx); 1588f59f1081SSepherosa Ziehau sc->msk_sysctl_tree = SYSCTL_ADD_NODE(&sc->msk_sysctl_ctx, 1589f59f1081SSepherosa Ziehau SYSCTL_STATIC_CHILDREN(_hw), 1590f59f1081SSepherosa Ziehau OID_AUTO, 1591f59f1081SSepherosa Ziehau device_get_nameunit(dev), 1592f59f1081SSepherosa Ziehau CTLFLAG_RD, 0, ""); 1593f59f1081SSepherosa Ziehau if (sc->msk_sysctl_tree == NULL) { 1594f59f1081SSepherosa Ziehau device_printf(dev, "can't add sysctl node\n"); 1595f59f1081SSepherosa Ziehau error = ENXIO; 1596f59f1081SSepherosa Ziehau goto fail; 1597f59f1081SSepherosa Ziehau } 1598f59f1081SSepherosa Ziehau 1599f59f1081SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->msk_sysctl_ctx, 1600f59f1081SSepherosa Ziehau SYSCTL_CHILDREN(sc->msk_sysctl_tree), 16012d586421SSepherosa Ziehau OID_AUTO, "process_limit", CTLTYPE_INT | CTLFLAG_RW, 1602f59f1081SSepherosa Ziehau &sc->msk_process_limit, 0, mskc_sysctl_proc_limit, 1603f59f1081SSepherosa Ziehau "I", "max number of Rx events to process"); 1604f59f1081SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->msk_sysctl_ctx, 1605f59f1081SSepherosa Ziehau SYSCTL_CHILDREN(sc->msk_sysctl_tree), 1606f59f1081SSepherosa Ziehau OID_AUTO, "intr_rate", CTLTYPE_INT | CTLFLAG_RW, 1607f59f1081SSepherosa Ziehau sc, 0, mskc_sysctl_intr_rate, 1608f59f1081SSepherosa Ziehau "I", "max number of interrupt per second"); 16095bda51d4SSepherosa Ziehau SYSCTL_ADD_INT(&sc->msk_sysctl_ctx, 16105bda51d4SSepherosa Ziehau SYSCTL_CHILDREN(sc->msk_sysctl_tree), OID_AUTO, 16115bda51d4SSepherosa Ziehau "defrag_avoided", CTLFLAG_RW, &sc->msk_defrag_avoided, 16125bda51d4SSepherosa Ziehau 0, "# of avoided m_defrag on TX path"); 16135bda51d4SSepherosa Ziehau SYSCTL_ADD_INT(&sc->msk_sysctl_ctx, 16145bda51d4SSepherosa Ziehau SYSCTL_CHILDREN(sc->msk_sysctl_tree), OID_AUTO, 16155bda51d4SSepherosa Ziehau "leading_copied", CTLFLAG_RW, &sc->msk_leading_copied, 16165bda51d4SSepherosa Ziehau 0, "# of leading copies on TX path"); 16175bda51d4SSepherosa Ziehau SYSCTL_ADD_INT(&sc->msk_sysctl_ctx, 16185bda51d4SSepherosa Ziehau SYSCTL_CHILDREN(sc->msk_sysctl_tree), OID_AUTO, 16195bda51d4SSepherosa Ziehau "trailing_copied", CTLFLAG_RW, &sc->msk_trailing_copied, 16205bda51d4SSepherosa Ziehau 0, "# of trailing copies on TX path"); 16212d586421SSepherosa Ziehau 16222d586421SSepherosa Ziehau sc->msk_pmd = CSR_READ_1(sc, B2_PMD_TYP); 16232d586421SSepherosa Ziehau if (sc->msk_pmd == 'L' || sc->msk_pmd == 'S') 16242d586421SSepherosa Ziehau sc->msk_coppertype = 0; 16252d586421SSepherosa Ziehau else 16262d586421SSepherosa Ziehau sc->msk_coppertype = 1; 16272d586421SSepherosa Ziehau /* Check number of MACs. */ 16282d586421SSepherosa Ziehau sc->msk_num_port = 1; 16292d586421SSepherosa Ziehau if ((CSR_READ_1(sc, B2_Y2_HW_RES) & CFG_DUAL_MAC_MSK) == 16302d586421SSepherosa Ziehau CFG_DUAL_MAC_MSK) { 16312d586421SSepherosa Ziehau if (!(CSR_READ_1(sc, B2_Y2_CLK_GATE) & Y2_STATUS_LNK2_INAC)) 16322d586421SSepherosa Ziehau sc->msk_num_port++; 16332d586421SSepherosa Ziehau } 16342d586421SSepherosa Ziehau 16352d586421SSepherosa Ziehau /* Check bus type. */ 163678c8aca9SSepherosa Ziehau if (pci_is_pcie(sc->msk_dev) == 0) { 16372d586421SSepherosa Ziehau sc->msk_bustype = MSK_PEX_BUS; 163878c8aca9SSepherosa Ziehau sc->msk_pciecap = pci_get_pciecap_ptr(sc->msk_dev); 163978c8aca9SSepherosa Ziehau } else if (pci_is_pcix(sc->msk_dev) == 0) { 16402d586421SSepherosa Ziehau sc->msk_bustype = MSK_PCIX_BUS; 164178c8aca9SSepherosa Ziehau sc->msk_pcixcap = pci_get_pcixcap_ptr(sc->msk_dev); 164278c8aca9SSepherosa Ziehau } else { 16432d586421SSepherosa Ziehau sc->msk_bustype = MSK_PCI_BUS; 164478c8aca9SSepherosa Ziehau } 16452d586421SSepherosa Ziehau 16462d586421SSepherosa Ziehau switch (sc->msk_hw_id) { 16472d586421SSepherosa Ziehau case CHIP_ID_YUKON_EC: 16482d586421SSepherosa Ziehau case CHIP_ID_YUKON_EC_U: 16492d586421SSepherosa Ziehau sc->msk_clock = 125; /* 125 Mhz */ 16502d586421SSepherosa Ziehau break; 1651d9e919c4SSepherosa Ziehau case CHIP_ID_YUKON_EX: 1652d9e919c4SSepherosa Ziehau sc->msk_clock = 125; /* 125 Mhz */ 1653d9e919c4SSepherosa Ziehau break; 16542d586421SSepherosa Ziehau case CHIP_ID_YUKON_FE: 16552d586421SSepherosa Ziehau sc->msk_clock = 100; /* 100 Mhz */ 1656793a2c89SSepherosa Ziehau sc->msk_pflags |= MSK_FLAG_FASTETHER; 16572d586421SSepherosa Ziehau break; 1658080bd27eSSepherosa Ziehau case CHIP_ID_YUKON_FE_P: 1659080bd27eSSepherosa Ziehau sc->msk_clock = 50; /* 50 Mhz */ 1660080bd27eSSepherosa Ziehau /* DESCV2 */ 1661080bd27eSSepherosa Ziehau sc->msk_pflags |= MSK_FLAG_FASTETHER; 1662080bd27eSSepherosa Ziehau if (sc->msk_hw_rev == CHIP_REV_YU_FE_P_A0) { 1663080bd27eSSepherosa Ziehau /* 1664080bd27eSSepherosa Ziehau * XXX 1665080bd27eSSepherosa Ziehau * FE+ A0 has status LE writeback bug so msk(4) 1666080bd27eSSepherosa Ziehau * does not rely on status word of received frame 1667080bd27eSSepherosa Ziehau * in msk_rxeof() which in turn disables all 1668080bd27eSSepherosa Ziehau * hardware assistance bits reported by the status 1669080bd27eSSepherosa Ziehau * word as well as validity of the recevied frame. 1670080bd27eSSepherosa Ziehau * Just pass received frames to upper stack with 1671080bd27eSSepherosa Ziehau * minimal test and let upper stack handle them. 1672080bd27eSSepherosa Ziehau */ 1673080bd27eSSepherosa Ziehau sc->msk_pflags |= MSK_FLAG_NORXCHK; 1674080bd27eSSepherosa Ziehau } 1675080bd27eSSepherosa Ziehau break; 16762d586421SSepherosa Ziehau case CHIP_ID_YUKON_XL: 16772d586421SSepherosa Ziehau sc->msk_clock = 156; /* 156 Mhz */ 16782d586421SSepherosa Ziehau break; 16790d557164SSepherosa Ziehau case CHIP_ID_YUKON_SUPR: 16800d557164SSepherosa Ziehau sc->msk_clock = 125; /* 125 MHz */ 16810d557164SSepherosa Ziehau break; 16823b7c5d2cSSepherosa Ziehau case CHIP_ID_YUKON_UL_2: 16833b7c5d2cSSepherosa Ziehau sc->msk_clock = 125; /* 125 Mhz */ 16843b7c5d2cSSepherosa Ziehau break; 16858e916b42SSepherosa Ziehau case CHIP_ID_YUKON_OPT: 16868e916b42SSepherosa Ziehau sc->msk_clock = 125; /* 125 MHz */ 16878e916b42SSepherosa Ziehau break; 16882d586421SSepherosa Ziehau default: 16892d586421SSepherosa Ziehau sc->msk_clock = 156; /* 156 Mhz */ 16902d586421SSepherosa Ziehau break; 16912d586421SSepherosa Ziehau } 16922d586421SSepherosa Ziehau 16932d586421SSepherosa Ziehau error = mskc_status_dma_alloc(sc); 16942d586421SSepherosa Ziehau if (error) 16952d586421SSepherosa Ziehau goto fail; 16962d586421SSepherosa Ziehau 16972d586421SSepherosa Ziehau /* Set base interrupt mask. */ 16982d586421SSepherosa Ziehau sc->msk_intrmask = Y2_IS_HW_ERR | Y2_IS_STAT_BMU; 16992d586421SSepherosa Ziehau sc->msk_intrhwemask = Y2_IS_TIST_OV | Y2_IS_MST_ERR | 17002d586421SSepherosa Ziehau Y2_IS_IRQ_STAT | Y2_IS_PCI_EXP | Y2_IS_PCI_NEXP; 17012d586421SSepherosa Ziehau 17022d586421SSepherosa Ziehau /* Reset the adapter. */ 17032d586421SSepherosa Ziehau mskc_reset(sc); 17042d586421SSepherosa Ziehau 17052d586421SSepherosa Ziehau error = mskc_setup_rambuffer(sc); 17062d586421SSepherosa Ziehau if (error) 17072d586421SSepherosa Ziehau goto fail; 17082d586421SSepherosa Ziehau 17092d586421SSepherosa Ziehau sc->msk_devs[MSK_PORT_A] = device_add_child(dev, "msk", -1); 17102d586421SSepherosa Ziehau if (sc->msk_devs[MSK_PORT_A] == NULL) { 17112d586421SSepherosa Ziehau device_printf(dev, "failed to add child for PORT_A\n"); 17122d586421SSepherosa Ziehau error = ENXIO; 17132d586421SSepherosa Ziehau goto fail; 17142d586421SSepherosa Ziehau } 17152d586421SSepherosa Ziehau port = kmalloc(sizeof(*port), M_DEVBUF, M_WAITOK); 17162d586421SSepherosa Ziehau *port = MSK_PORT_A; 17172d586421SSepherosa Ziehau device_set_ivars(sc->msk_devs[MSK_PORT_A], port); 17182d586421SSepherosa Ziehau 17192d586421SSepherosa Ziehau if (sc->msk_num_port > 1) { 17202d586421SSepherosa Ziehau sc->msk_devs[MSK_PORT_B] = device_add_child(dev, "msk", -1); 17212d586421SSepherosa Ziehau if (sc->msk_devs[MSK_PORT_B] == NULL) { 17222d586421SSepherosa Ziehau device_printf(dev, "failed to add child for PORT_B\n"); 17232d586421SSepherosa Ziehau error = ENXIO; 17242d586421SSepherosa Ziehau goto fail; 17252d586421SSepherosa Ziehau } 17262d586421SSepherosa Ziehau port = kmalloc(sizeof(*port), M_DEVBUF, M_WAITOK); 17272d586421SSepherosa Ziehau *port = MSK_PORT_B; 17282d586421SSepherosa Ziehau device_set_ivars(sc->msk_devs[MSK_PORT_B], port); 17292d586421SSepherosa Ziehau } 17302d586421SSepherosa Ziehau 17312d586421SSepherosa Ziehau bus_generic_attach(dev); 17322d586421SSepherosa Ziehau 17332d586421SSepherosa Ziehau error = bus_setup_intr(dev, sc->msk_irq, INTR_MPSAFE, 17342d586421SSepherosa Ziehau mskc_intr, sc, &sc->msk_intrhand, 17352d586421SSepherosa Ziehau &sc->msk_serializer); 17362d586421SSepherosa Ziehau if (error) { 17372d586421SSepherosa Ziehau device_printf(dev, "couldn't set up interrupt handler\n"); 17382d586421SSepherosa Ziehau goto fail; 17392d586421SSepherosa Ziehau } 17409db4b353SSepherosa Ziehau 174128e81a28SSepherosa Ziehau cpuid = rman_get_cpuid(sc->msk_irq); 17429db4b353SSepherosa Ziehau KKASSERT(cpuid >= 0 && cpuid < ncpus); 17439db4b353SSepherosa Ziehau 17449db4b353SSepherosa Ziehau if (sc->msk_if[0] != NULL) 17459db4b353SSepherosa Ziehau sc->msk_if[0]->msk_ifp->if_cpuid = cpuid; 17469db4b353SSepherosa Ziehau if (sc->msk_if[1] != NULL) 17479db4b353SSepherosa Ziehau sc->msk_if[1]->msk_ifp->if_cpuid = cpuid; 17482d586421SSepherosa Ziehau return 0; 17492d586421SSepherosa Ziehau fail: 17502d586421SSepherosa Ziehau mskc_detach(dev); 17512d586421SSepherosa Ziehau return (error); 17522d586421SSepherosa Ziehau } 17532d586421SSepherosa Ziehau 17542d586421SSepherosa Ziehau /* 17552d586421SSepherosa Ziehau * Shutdown hardware and free up resources. This can be called any 17562d586421SSepherosa Ziehau * time after the mutex has been initialized. It is called in both 17572d586421SSepherosa Ziehau * the error case in attach and the normal detach case so it needs 17582d586421SSepherosa Ziehau * to be careful about only freeing resources that have actually been 17592d586421SSepherosa Ziehau * allocated. 17602d586421SSepherosa Ziehau */ 17612d586421SSepherosa Ziehau static int 17622d586421SSepherosa Ziehau msk_detach(device_t dev) 17632d586421SSepherosa Ziehau { 17642d586421SSepherosa Ziehau struct msk_if_softc *sc_if = device_get_softc(dev); 17652d586421SSepherosa Ziehau 17662d586421SSepherosa Ziehau if (device_is_attached(dev)) { 17672d586421SSepherosa Ziehau struct msk_softc *sc = sc_if->msk_softc; 17682d586421SSepherosa Ziehau struct ifnet *ifp = &sc_if->arpcom.ac_if; 17692d586421SSepherosa Ziehau 17702d586421SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 17712d586421SSepherosa Ziehau 17722d586421SSepherosa Ziehau if (sc->msk_intrhand != NULL) { 17732d586421SSepherosa Ziehau if (sc->msk_if[MSK_PORT_A] != NULL) 17742d586421SSepherosa Ziehau msk_stop(sc->msk_if[MSK_PORT_A]); 17752d586421SSepherosa Ziehau if (sc->msk_if[MSK_PORT_B] != NULL) 17762d586421SSepherosa Ziehau msk_stop(sc->msk_if[MSK_PORT_B]); 17772d586421SSepherosa Ziehau 17782d586421SSepherosa Ziehau bus_teardown_intr(sc->msk_dev, sc->msk_irq, 17792d586421SSepherosa Ziehau sc->msk_intrhand); 17802d586421SSepherosa Ziehau sc->msk_intrhand = NULL; 17812d586421SSepherosa Ziehau } 17822d586421SSepherosa Ziehau 17832d586421SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 17842d586421SSepherosa Ziehau 17852d586421SSepherosa Ziehau ether_ifdetach(ifp); 17862d586421SSepherosa Ziehau } 17872d586421SSepherosa Ziehau 17882d586421SSepherosa Ziehau if (sc_if->msk_miibus != NULL) 17892d586421SSepherosa Ziehau device_delete_child(dev, sc_if->msk_miibus); 17902d586421SSepherosa Ziehau 17912d586421SSepherosa Ziehau msk_txrx_dma_free(sc_if); 17922d586421SSepherosa Ziehau return (0); 17932d586421SSepherosa Ziehau } 17942d586421SSepherosa Ziehau 17952d586421SSepherosa Ziehau static int 17962d586421SSepherosa Ziehau mskc_detach(device_t dev) 17972d586421SSepherosa Ziehau { 17982d586421SSepherosa Ziehau struct msk_softc *sc = device_get_softc(dev); 17992d586421SSepherosa Ziehau int *port, i; 18002d586421SSepherosa Ziehau 18012d586421SSepherosa Ziehau #ifdef INVARIANTS 18022d586421SSepherosa Ziehau if (device_is_attached(dev)) { 18032d586421SSepherosa Ziehau KASSERT(sc->msk_intrhand == NULL, 1804ed20d0e3SSascha Wildner ("intr is not torn down yet")); 18052d586421SSepherosa Ziehau } 18062d586421SSepherosa Ziehau #endif 18072d586421SSepherosa Ziehau 18082d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; ++i) { 18092d586421SSepherosa Ziehau if (sc->msk_devs[i] != NULL) { 18102d586421SSepherosa Ziehau port = device_get_ivars(sc->msk_devs[i]); 18112d586421SSepherosa Ziehau if (port != NULL) { 18122d586421SSepherosa Ziehau kfree(port, M_DEVBUF); 18132d586421SSepherosa Ziehau device_set_ivars(sc->msk_devs[i], NULL); 18142d586421SSepherosa Ziehau } 18152d586421SSepherosa Ziehau device_delete_child(dev, sc->msk_devs[i]); 18162d586421SSepherosa Ziehau } 18172d586421SSepherosa Ziehau } 18182d586421SSepherosa Ziehau 18192d586421SSepherosa Ziehau /* Disable all interrupts. */ 18202d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, 0); 18212d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 18222d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_HWE_IMSK, 0); 18232d586421SSepherosa Ziehau CSR_READ_4(sc, B0_HWE_IMSK); 18242d586421SSepherosa Ziehau 18252d586421SSepherosa Ziehau /* LED Off. */ 18262d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, Y2_LED_STAT_OFF); 18272d586421SSepherosa Ziehau 18282d586421SSepherosa Ziehau /* Put hardware reset. */ 18292d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_SET); 18302d586421SSepherosa Ziehau 18312d586421SSepherosa Ziehau mskc_status_dma_free(sc); 18322d586421SSepherosa Ziehau 18332d586421SSepherosa Ziehau if (sc->msk_irq != NULL) { 18342d586421SSepherosa Ziehau bus_release_resource(dev, SYS_RES_IRQ, sc->msk_irq_rid, 18352d586421SSepherosa Ziehau sc->msk_irq); 18362d586421SSepherosa Ziehau } 18372d586421SSepherosa Ziehau if (sc->msk_res != NULL) { 18382d586421SSepherosa Ziehau bus_release_resource(dev, sc->msk_res_type, sc->msk_res_rid, 18392d586421SSepherosa Ziehau sc->msk_res); 18402d586421SSepherosa Ziehau } 18412d586421SSepherosa Ziehau 1842f59f1081SSepherosa Ziehau if (sc->msk_sysctl_tree != NULL) 1843f59f1081SSepherosa Ziehau sysctl_ctx_free(&sc->msk_sysctl_ctx); 1844f59f1081SSepherosa Ziehau 18452d586421SSepherosa Ziehau return (0); 18462d586421SSepherosa Ziehau } 18472d586421SSepherosa Ziehau 18482d586421SSepherosa Ziehau /* Create status DMA region. */ 18492d586421SSepherosa Ziehau static int 18502d586421SSepherosa Ziehau mskc_status_dma_alloc(struct msk_softc *sc) 18512d586421SSepherosa Ziehau { 1852c78f83cbSSepherosa Ziehau bus_dmamem_t dmem; 18532d586421SSepherosa Ziehau int error; 18542d586421SSepherosa Ziehau 1855c78f83cbSSepherosa Ziehau error = bus_dmamem_coherent(NULL/* XXX parent */, MSK_STAT_ALIGN, 0, 1856c78f83cbSSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 1857c78f83cbSSepherosa Ziehau MSK_STAT_RING_SZ, BUS_DMA_WAITOK | BUS_DMA_ZERO, &dmem); 18582d586421SSepherosa Ziehau if (error) { 18592d586421SSepherosa Ziehau device_printf(sc->msk_dev, 1860c78f83cbSSepherosa Ziehau "failed to create status coherent DMA memory\n"); 1861c78f83cbSSepherosa Ziehau return error; 18622d586421SSepherosa Ziehau } 1863c78f83cbSSepherosa Ziehau sc->msk_stat_tag = dmem.dmem_tag; 1864c78f83cbSSepherosa Ziehau sc->msk_stat_map = dmem.dmem_map; 1865c78f83cbSSepherosa Ziehau sc->msk_stat_ring = dmem.dmem_addr; 1866c78f83cbSSepherosa Ziehau sc->msk_stat_ring_paddr = dmem.dmem_busaddr; 18672d586421SSepherosa Ziehau 18682d586421SSepherosa Ziehau return (0); 18692d586421SSepherosa Ziehau } 18702d586421SSepherosa Ziehau 18712d586421SSepherosa Ziehau static void 18722d586421SSepherosa Ziehau mskc_status_dma_free(struct msk_softc *sc) 18732d586421SSepherosa Ziehau { 18742d586421SSepherosa Ziehau /* Destroy status block. */ 18752d586421SSepherosa Ziehau if (sc->msk_stat_tag) { 18762d586421SSepherosa Ziehau bus_dmamap_unload(sc->msk_stat_tag, sc->msk_stat_map); 18772d586421SSepherosa Ziehau bus_dmamem_free(sc->msk_stat_tag, sc->msk_stat_ring, 18782d586421SSepherosa Ziehau sc->msk_stat_map); 18792d586421SSepherosa Ziehau bus_dma_tag_destroy(sc->msk_stat_tag); 18802d586421SSepherosa Ziehau sc->msk_stat_tag = NULL; 18812d586421SSepherosa Ziehau } 18822d586421SSepherosa Ziehau } 18832d586421SSepherosa Ziehau 18842d586421SSepherosa Ziehau static int 18852d586421SSepherosa Ziehau msk_txrx_dma_alloc(struct msk_if_softc *sc_if) 18862d586421SSepherosa Ziehau { 18872d586421SSepherosa Ziehau int error, i, j; 18882d586421SSepherosa Ziehau #ifdef MSK_JUMBO 18892d586421SSepherosa Ziehau struct msk_rxdesc *jrxd; 18902d586421SSepherosa Ziehau struct msk_jpool_entry *entry; 18912d586421SSepherosa Ziehau uint8_t *ptr; 18922d586421SSepherosa Ziehau #endif 18932a9b20a4SSepherosa Ziehau bus_size_t rxalign; 18942d586421SSepherosa Ziehau 18952d586421SSepherosa Ziehau /* Create parent DMA tag. */ 18962d586421SSepherosa Ziehau /* 18972d586421SSepherosa Ziehau * XXX 18982d586421SSepherosa Ziehau * It seems that Yukon II supports full 64bits DMA operations. But 18992d586421SSepherosa Ziehau * it needs two descriptors(list elements) for 64bits DMA operations. 19002d586421SSepherosa Ziehau * Since we don't know what DMA address mappings(32bits or 64bits) 19012d586421SSepherosa Ziehau * would be used in advance for each mbufs, we limits its DMA space 19022d586421SSepherosa Ziehau * to be in range of 32bits address space. Otherwise, we should check 19032d586421SSepherosa Ziehau * what DMA address is used and chain another descriptor for the 19042d586421SSepherosa Ziehau * 64bits DMA operation. This also means descriptor ring size is 19052d586421SSepherosa Ziehau * variable. Limiting DMA address to be in 32bit address space greatly 19062d586421SSepherosa Ziehau * simplyfies descriptor handling and possibly would increase 19072d586421SSepherosa Ziehau * performance a bit due to efficient handling of descriptors. 19082d586421SSepherosa Ziehau * Apart from harassing checksum offloading mechanisms, it seems 19092d586421SSepherosa Ziehau * it's really bad idea to use a seperate descriptor for 64bit 19102d586421SSepherosa Ziehau * DMA operation to save small descriptor memory. Anyway, I've 19112d586421SSepherosa Ziehau * never seen these exotic scheme on ethernet interface hardware. 19122d586421SSepherosa Ziehau */ 19132d586421SSepherosa Ziehau error = bus_dma_tag_create( 19142d586421SSepherosa Ziehau NULL, /* parent */ 19152d586421SSepherosa Ziehau 1, 0, /* alignment, boundary */ 19162d586421SSepherosa Ziehau BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 19172d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 19182d586421SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 19192d586421SSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 19202d586421SSepherosa Ziehau 0, /* nsegments */ 19212d586421SSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 19222d586421SSepherosa Ziehau 0, /* flags */ 19232d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_parent_tag); 19242d586421SSepherosa Ziehau if (error) { 19252d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 19262d586421SSepherosa Ziehau "failed to create parent DMA tag\n"); 19272d586421SSepherosa Ziehau return error; 19282d586421SSepherosa Ziehau } 19292d586421SSepherosa Ziehau 19302d586421SSepherosa Ziehau /* Create DMA stuffs for Tx ring. */ 19312d586421SSepherosa Ziehau error = msk_dmamem_create(sc_if->msk_if_dev, MSK_TX_RING_SZ, 19322d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_tx_ring_tag, 1933da44240fSMatthew Dillon (void *)&sc_if->msk_rdata.msk_tx_ring, 19342d586421SSepherosa Ziehau &sc_if->msk_rdata.msk_tx_ring_paddr, 19352d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_tx_ring_map); 19362d586421SSepherosa Ziehau if (error) { 19372d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 19382d586421SSepherosa Ziehau "failed to create TX ring DMA stuffs\n"); 19392d586421SSepherosa Ziehau return error; 19402d586421SSepherosa Ziehau } 19412d586421SSepherosa Ziehau 19422d586421SSepherosa Ziehau /* Create DMA stuffs for Rx ring. */ 19432d586421SSepherosa Ziehau error = msk_dmamem_create(sc_if->msk_if_dev, MSK_RX_RING_SZ, 19442d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_rx_ring_tag, 1945da44240fSMatthew Dillon (void *)&sc_if->msk_rdata.msk_rx_ring, 19462d586421SSepherosa Ziehau &sc_if->msk_rdata.msk_rx_ring_paddr, 19472d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_rx_ring_map); 19482d586421SSepherosa Ziehau if (error) { 19492d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 19502d586421SSepherosa Ziehau "failed to create RX ring DMA stuffs\n"); 19512d586421SSepherosa Ziehau return error; 19522d586421SSepherosa Ziehau } 19532d586421SSepherosa Ziehau 19542d586421SSepherosa Ziehau /* Create tag for Tx buffers. */ 19552d586421SSepherosa Ziehau error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ 19562d586421SSepherosa Ziehau 1, 0, /* alignment, boundary */ 19572d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* lowaddr */ 19582d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 19592d586421SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 1960ad3a1ee4SSepherosa Ziehau MSK_JUMBO_FRAMELEN, /* maxsize */ 19612d586421SSepherosa Ziehau MSK_MAXTXSEGS, /* nsegments */ 1962ad3a1ee4SSepherosa Ziehau MSK_MAXSGSIZE, /* maxsegsize */ 1963ad3a1ee4SSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK | 1964ad3a1ee4SSepherosa Ziehau BUS_DMA_ONEBPAGE, /* flags */ 19652d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_tx_tag); 19662d586421SSepherosa Ziehau if (error) { 19672d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 19682d586421SSepherosa Ziehau "failed to create Tx DMA tag\n"); 19692d586421SSepherosa Ziehau return error; 19702d586421SSepherosa Ziehau } 19712d586421SSepherosa Ziehau 19722d586421SSepherosa Ziehau /* Create DMA maps for Tx buffers. */ 19732d586421SSepherosa Ziehau for (i = 0; i < MSK_TX_RING_CNT; i++) { 19742d586421SSepherosa Ziehau struct msk_txdesc *txd = &sc_if->msk_cdata.msk_txdesc[i]; 19752d586421SSepherosa Ziehau 1976ad3a1ee4SSepherosa Ziehau error = bus_dmamap_create(sc_if->msk_cdata.msk_tx_tag, 1977ad3a1ee4SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE, 19782d586421SSepherosa Ziehau &txd->tx_dmamap); 19792d586421SSepherosa Ziehau if (error) { 19802d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 19812d586421SSepherosa Ziehau "failed to create %dth Tx dmamap\n", i); 19822d586421SSepherosa Ziehau 19832d586421SSepherosa Ziehau for (j = 0; j < i; ++j) { 19842d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[j]; 19852d586421SSepherosa Ziehau bus_dmamap_destroy(sc_if->msk_cdata.msk_tx_tag, 19862d586421SSepherosa Ziehau txd->tx_dmamap); 19872d586421SSepherosa Ziehau } 19882d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_tx_tag); 19892d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_tag = NULL; 19902d586421SSepherosa Ziehau 19912d586421SSepherosa Ziehau return error; 19922d586421SSepherosa Ziehau } 19932d586421SSepherosa Ziehau } 19942d586421SSepherosa Ziehau 19952a9b20a4SSepherosa Ziehau /* 19962a9b20a4SSepherosa Ziehau * Workaround hardware hang which seems to happen when Rx buffer 19972a9b20a4SSepherosa Ziehau * is not aligned on multiple of FIFO word(8 bytes). 19982a9b20a4SSepherosa Ziehau */ 19992a9b20a4SSepherosa Ziehau if (sc_if->msk_flags & MSK_FLAG_RAMBUF) 20002a9b20a4SSepherosa Ziehau rxalign = MSK_RX_BUF_ALIGN; 20012a9b20a4SSepherosa Ziehau else 20022a9b20a4SSepherosa Ziehau rxalign = 1; 20032a9b20a4SSepherosa Ziehau 20042d586421SSepherosa Ziehau /* Create tag for Rx buffers. */ 20052d586421SSepherosa Ziehau error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ 20062a9b20a4SSepherosa Ziehau rxalign, 0, /* alignment, boundary */ 20072d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* lowaddr */ 20082d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 20092d586421SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 20102d586421SSepherosa Ziehau MCLBYTES, /* maxsize */ 20112d586421SSepherosa Ziehau 1, /* nsegments */ 20122d586421SSepherosa Ziehau MCLBYTES, /* maxsegsize */ 20132a9b20a4SSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_ALIGNED | 20142a9b20a4SSepherosa Ziehau BUS_DMA_WAITOK, /* flags */ 20152d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_rx_tag); 20162d586421SSepherosa Ziehau if (error) { 20172d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 20182d586421SSepherosa Ziehau "failed to create Rx DMA tag\n"); 20192d586421SSepherosa Ziehau return error; 20202d586421SSepherosa Ziehau } 20212d586421SSepherosa Ziehau 20222d586421SSepherosa Ziehau /* Create DMA maps for Rx buffers. */ 2023ad3a1ee4SSepherosa Ziehau error = bus_dmamap_create(sc_if->msk_cdata.msk_rx_tag, BUS_DMA_WAITOK, 20242d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_rx_sparemap); 20252d586421SSepherosa Ziehau if (error) { 20262d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 20272d586421SSepherosa Ziehau "failed to create spare Rx dmamap\n"); 20282d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_rx_tag); 20292d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_tag = NULL; 20302d586421SSepherosa Ziehau return error; 20312d586421SSepherosa Ziehau } 20322d586421SSepherosa Ziehau for (i = 0; i < MSK_RX_RING_CNT; i++) { 20332d586421SSepherosa Ziehau struct msk_rxdesc *rxd = &sc_if->msk_cdata.msk_rxdesc[i]; 20342d586421SSepherosa Ziehau 2035ad3a1ee4SSepherosa Ziehau error = bus_dmamap_create(sc_if->msk_cdata.msk_rx_tag, 2036ad3a1ee4SSepherosa Ziehau BUS_DMA_WAITOK, &rxd->rx_dmamap); 20372d586421SSepherosa Ziehau if (error) { 20382d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 20392d586421SSepherosa Ziehau "failed to create %dth Rx dmamap\n", i); 20402d586421SSepherosa Ziehau 20412d586421SSepherosa Ziehau for (j = 0; j < i; ++j) { 20422d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[j]; 20432d586421SSepherosa Ziehau bus_dmamap_destroy(sc_if->msk_cdata.msk_rx_tag, 20442d586421SSepherosa Ziehau rxd->rx_dmamap); 20452d586421SSepherosa Ziehau } 20467f582564SSepherosa Ziehau bus_dmamap_destroy(sc_if->msk_cdata.msk_rx_tag, 20477f582564SSepherosa Ziehau sc_if->msk_cdata.msk_rx_sparemap); 20482d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_rx_tag); 20492d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_tag = NULL; 20502d586421SSepherosa Ziehau 20512d586421SSepherosa Ziehau return error; 20522d586421SSepherosa Ziehau } 20532d586421SSepherosa Ziehau } 20542d586421SSepherosa Ziehau 20552d586421SSepherosa Ziehau #ifdef MSK_JUMBO 20562d586421SSepherosa Ziehau SLIST_INIT(&sc_if->msk_jfree_listhead); 20572d586421SSepherosa Ziehau SLIST_INIT(&sc_if->msk_jinuse_listhead); 20582d586421SSepherosa Ziehau 20592d586421SSepherosa Ziehau /* Create tag for jumbo Rx ring. */ 20602d586421SSepherosa Ziehau error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ 20612d586421SSepherosa Ziehau MSK_RING_ALIGN, 0, /* alignment, boundary */ 20622d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* lowaddr */ 20632d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 20642d586421SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 20652d586421SSepherosa Ziehau MSK_JUMBO_RX_RING_SZ, /* maxsize */ 20662d586421SSepherosa Ziehau 1, /* nsegments */ 20672d586421SSepherosa Ziehau MSK_JUMBO_RX_RING_SZ, /* maxsegsize */ 20682d586421SSepherosa Ziehau 0, /* flags */ 20692d586421SSepherosa Ziehau NULL, NULL, /* lockfunc, lockarg */ 20702d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_jumbo_rx_ring_tag); 20712d586421SSepherosa Ziehau if (error != 0) { 20722d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 20732d586421SSepherosa Ziehau "failed to create jumbo Rx ring DMA tag\n"); 20742d586421SSepherosa Ziehau goto fail; 20752d586421SSepherosa Ziehau } 20762d586421SSepherosa Ziehau 20772d586421SSepherosa Ziehau /* Allocate DMA'able memory and load the DMA map for jumbo Rx ring. */ 20782d586421SSepherosa Ziehau error = bus_dmamem_alloc(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, 20792d586421SSepherosa Ziehau (void **)&sc_if->msk_rdata.msk_jumbo_rx_ring, 20802d586421SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, 20812d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_jumbo_rx_ring_map); 20822d586421SSepherosa Ziehau if (error != 0) { 20832d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 20842d586421SSepherosa Ziehau "failed to allocate DMA'able memory for jumbo Rx ring\n"); 20852d586421SSepherosa Ziehau goto fail; 20862d586421SSepherosa Ziehau } 20872d586421SSepherosa Ziehau 20882d586421SSepherosa Ziehau ctx.msk_busaddr = 0; 20892d586421SSepherosa Ziehau error = bus_dmamap_load(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, 20902d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_map, 20912d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_rx_ring, MSK_JUMBO_RX_RING_SZ, 20922d586421SSepherosa Ziehau msk_dmamap_cb, &ctx, 0); 20932d586421SSepherosa Ziehau if (error != 0) { 20942d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 20952d586421SSepherosa Ziehau "failed to load DMA'able memory for jumbo Rx ring\n"); 20962d586421SSepherosa Ziehau goto fail; 20972d586421SSepherosa Ziehau } 20982d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_rx_ring_paddr = ctx.msk_busaddr; 20992d586421SSepherosa Ziehau 21002d586421SSepherosa Ziehau /* Create tag for jumbo buffer blocks. */ 21012d586421SSepherosa Ziehau error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ 21022d586421SSepherosa Ziehau PAGE_SIZE, 0, /* alignment, boundary */ 21032d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* lowaddr */ 21042d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 21052d586421SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 21062d586421SSepherosa Ziehau MSK_JMEM, /* maxsize */ 21072d586421SSepherosa Ziehau 1, /* nsegments */ 21082d586421SSepherosa Ziehau MSK_JMEM, /* maxsegsize */ 21092d586421SSepherosa Ziehau 0, /* flags */ 21102d586421SSepherosa Ziehau NULL, NULL, /* lockfunc, lockarg */ 21112d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_jumbo_tag); 21122d586421SSepherosa Ziehau if (error != 0) { 21132d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 21142d586421SSepherosa Ziehau "failed to create jumbo Rx buffer block DMA tag\n"); 21152d586421SSepherosa Ziehau goto fail; 21162d586421SSepherosa Ziehau } 21172d586421SSepherosa Ziehau 21182d586421SSepherosa Ziehau /* Create tag for jumbo Rx buffers. */ 21192d586421SSepherosa Ziehau error = bus_dma_tag_create(sc_if->msk_cdata.msk_parent_tag,/* parent */ 21202d586421SSepherosa Ziehau PAGE_SIZE, 0, /* alignment, boundary */ 21212d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* lowaddr */ 21222d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 21232d586421SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 21242d586421SSepherosa Ziehau MCLBYTES * MSK_MAXRXSEGS, /* maxsize */ 21252d586421SSepherosa Ziehau MSK_MAXRXSEGS, /* nsegments */ 21262d586421SSepherosa Ziehau MSK_JLEN, /* maxsegsize */ 21272d586421SSepherosa Ziehau 0, /* flags */ 21282d586421SSepherosa Ziehau NULL, NULL, /* lockfunc, lockarg */ 21292d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_jumbo_rx_tag); 21302d586421SSepherosa Ziehau if (error != 0) { 21312d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 21322d586421SSepherosa Ziehau "failed to create jumbo Rx DMA tag\n"); 21332d586421SSepherosa Ziehau goto fail; 21342d586421SSepherosa Ziehau } 21352d586421SSepherosa Ziehau 21362d586421SSepherosa Ziehau /* Create DMA maps for jumbo Rx buffers. */ 21372d586421SSepherosa Ziehau if ((error = bus_dmamap_create(sc_if->msk_cdata.msk_jumbo_rx_tag, 0, 21382d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_jumbo_rx_sparemap)) != 0) { 21392d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 21402d586421SSepherosa Ziehau "failed to create spare jumbo Rx dmamap\n"); 21412d586421SSepherosa Ziehau goto fail; 21422d586421SSepherosa Ziehau } 21432d586421SSepherosa Ziehau for (i = 0; i < MSK_JUMBO_RX_RING_CNT; i++) { 21442d586421SSepherosa Ziehau jrxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[i]; 21452d586421SSepherosa Ziehau jrxd->rx_m = NULL; 21462d586421SSepherosa Ziehau jrxd->rx_dmamap = NULL; 21472d586421SSepherosa Ziehau error = bus_dmamap_create(sc_if->msk_cdata.msk_jumbo_rx_tag, 0, 21482d586421SSepherosa Ziehau &jrxd->rx_dmamap); 21492d586421SSepherosa Ziehau if (error != 0) { 21502d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 21512d586421SSepherosa Ziehau "failed to create jumbo Rx dmamap\n"); 21522d586421SSepherosa Ziehau goto fail; 21532d586421SSepherosa Ziehau } 21542d586421SSepherosa Ziehau } 21552d586421SSepherosa Ziehau 21562d586421SSepherosa Ziehau /* Allocate DMA'able memory and load the DMA map for jumbo buf. */ 21572d586421SSepherosa Ziehau error = bus_dmamem_alloc(sc_if->msk_cdata.msk_jumbo_tag, 21582d586421SSepherosa Ziehau (void **)&sc_if->msk_rdata.msk_jumbo_buf, 21592d586421SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, 21602d586421SSepherosa Ziehau &sc_if->msk_cdata.msk_jumbo_map); 21612d586421SSepherosa Ziehau if (error != 0) { 21622d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 21632d586421SSepherosa Ziehau "failed to allocate DMA'able memory for jumbo buf\n"); 21642d586421SSepherosa Ziehau goto fail; 21652d586421SSepherosa Ziehau } 21662d586421SSepherosa Ziehau 21672d586421SSepherosa Ziehau ctx.msk_busaddr = 0; 21682d586421SSepherosa Ziehau error = bus_dmamap_load(sc_if->msk_cdata.msk_jumbo_tag, 21692d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_map, sc_if->msk_rdata.msk_jumbo_buf, 21702d586421SSepherosa Ziehau MSK_JMEM, msk_dmamap_cb, &ctx, 0); 21712d586421SSepherosa Ziehau if (error != 0) { 21722d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 21732d586421SSepherosa Ziehau "failed to load DMA'able memory for jumbobuf\n"); 21742d586421SSepherosa Ziehau goto fail; 21752d586421SSepherosa Ziehau } 21762d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_buf_paddr = ctx.msk_busaddr; 21772d586421SSepherosa Ziehau 21782d586421SSepherosa Ziehau /* 21792d586421SSepherosa Ziehau * Now divide it up into 9K pieces and save the addresses 21802d586421SSepherosa Ziehau * in an array. 21812d586421SSepherosa Ziehau */ 21822d586421SSepherosa Ziehau ptr = sc_if->msk_rdata.msk_jumbo_buf; 21832d586421SSepherosa Ziehau for (i = 0; i < MSK_JSLOTS; i++) { 21842d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jslots[i] = ptr; 21852d586421SSepherosa Ziehau ptr += MSK_JLEN; 21862d586421SSepherosa Ziehau entry = malloc(sizeof(struct msk_jpool_entry), 21872d586421SSepherosa Ziehau M_DEVBUF, M_WAITOK); 21882d586421SSepherosa Ziehau if (entry == NULL) { 21892d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 21902d586421SSepherosa Ziehau "no memory for jumbo buffers!\n"); 21912d586421SSepherosa Ziehau error = ENOMEM; 21922d586421SSepherosa Ziehau goto fail; 21932d586421SSepherosa Ziehau } 21942d586421SSepherosa Ziehau entry->slot = i; 21952d586421SSepherosa Ziehau SLIST_INSERT_HEAD(&sc_if->msk_jfree_listhead, entry, 21962d586421SSepherosa Ziehau jpool_entries); 21972d586421SSepherosa Ziehau } 21982d586421SSepherosa Ziehau #endif 21992d586421SSepherosa Ziehau return 0; 22002d586421SSepherosa Ziehau } 22012d586421SSepherosa Ziehau 22022d586421SSepherosa Ziehau static void 22032d586421SSepherosa Ziehau msk_txrx_dma_free(struct msk_if_softc *sc_if) 22042d586421SSepherosa Ziehau { 22052d586421SSepherosa Ziehau struct msk_txdesc *txd; 22062d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 22072d586421SSepherosa Ziehau #ifdef MSK_JUMBO 22082d586421SSepherosa Ziehau struct msk_rxdesc *jrxd; 22092d586421SSepherosa Ziehau struct msk_jpool_entry *entry; 22102d586421SSepherosa Ziehau #endif 22112d586421SSepherosa Ziehau int i; 22122d586421SSepherosa Ziehau 22132d586421SSepherosa Ziehau #ifdef MSK_JUMBO 22142d586421SSepherosa Ziehau MSK_JLIST_LOCK(sc_if); 22152d586421SSepherosa Ziehau while ((entry = SLIST_FIRST(&sc_if->msk_jinuse_listhead))) { 22162d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 22172d586421SSepherosa Ziehau "asked to free buffer that is in use!\n"); 22182d586421SSepherosa Ziehau SLIST_REMOVE_HEAD(&sc_if->msk_jinuse_listhead, jpool_entries); 22192d586421SSepherosa Ziehau SLIST_INSERT_HEAD(&sc_if->msk_jfree_listhead, entry, 22202d586421SSepherosa Ziehau jpool_entries); 22212d586421SSepherosa Ziehau } 22222d586421SSepherosa Ziehau 22232d586421SSepherosa Ziehau while (!SLIST_EMPTY(&sc_if->msk_jfree_listhead)) { 22242d586421SSepherosa Ziehau entry = SLIST_FIRST(&sc_if->msk_jfree_listhead); 22252d586421SSepherosa Ziehau SLIST_REMOVE_HEAD(&sc_if->msk_jfree_listhead, jpool_entries); 22262d586421SSepherosa Ziehau free(entry, M_DEVBUF); 22272d586421SSepherosa Ziehau } 22282d586421SSepherosa Ziehau MSK_JLIST_UNLOCK(sc_if); 22292d586421SSepherosa Ziehau 22302d586421SSepherosa Ziehau /* Destroy jumbo buffer block. */ 22312d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_jumbo_map) 22322d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_jumbo_tag, 22332d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_map); 22342d586421SSepherosa Ziehau 22352d586421SSepherosa Ziehau if (sc_if->msk_rdata.msk_jumbo_buf) { 22362d586421SSepherosa Ziehau bus_dmamem_free(sc_if->msk_cdata.msk_jumbo_tag, 22372d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_buf, 22382d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_map); 22392d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_buf = NULL; 22402d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_map = NULL; 22412d586421SSepherosa Ziehau } 22422d586421SSepherosa Ziehau 22432d586421SSepherosa Ziehau /* Jumbo Rx ring. */ 22442d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_jumbo_rx_ring_tag) { 22452d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_jumbo_rx_ring_map) 22462d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, 22472d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_map); 22482d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_jumbo_rx_ring_map && 22492d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_rx_ring) 22502d586421SSepherosa Ziehau bus_dmamem_free(sc_if->msk_cdata.msk_jumbo_rx_ring_tag, 22512d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_rx_ring, 22522d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_map); 22532d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_rx_ring = NULL; 22542d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_map = NULL; 22552d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_jumbo_rx_ring_tag); 22562d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_tag = NULL; 22572d586421SSepherosa Ziehau } 22582d586421SSepherosa Ziehau 22592d586421SSepherosa Ziehau /* Jumbo Rx buffers. */ 22602d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_jumbo_rx_tag) { 22612d586421SSepherosa Ziehau for (i = 0; i < MSK_JUMBO_RX_RING_CNT; i++) { 22622d586421SSepherosa Ziehau jrxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[i]; 22632d586421SSepherosa Ziehau if (jrxd->rx_dmamap) { 22642d586421SSepherosa Ziehau bus_dmamap_destroy( 22652d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_tag, 22662d586421SSepherosa Ziehau jrxd->rx_dmamap); 22672d586421SSepherosa Ziehau jrxd->rx_dmamap = NULL; 22682d586421SSepherosa Ziehau } 22692d586421SSepherosa Ziehau } 22702d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_jumbo_rx_sparemap) { 22712d586421SSepherosa Ziehau bus_dmamap_destroy(sc_if->msk_cdata.msk_jumbo_rx_tag, 22722d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_sparemap); 22732d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_sparemap = 0; 22742d586421SSepherosa Ziehau } 22752d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_jumbo_rx_tag); 22762d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_tag = NULL; 22772d586421SSepherosa Ziehau } 22782d586421SSepherosa Ziehau #endif 22792d586421SSepherosa Ziehau 22802d586421SSepherosa Ziehau /* Tx ring. */ 22812d586421SSepherosa Ziehau msk_dmamem_destroy(sc_if->msk_cdata.msk_tx_ring_tag, 22822d586421SSepherosa Ziehau sc_if->msk_rdata.msk_tx_ring, 22832d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_ring_map); 22842d586421SSepherosa Ziehau 22852d586421SSepherosa Ziehau /* Rx ring. */ 22862d586421SSepherosa Ziehau msk_dmamem_destroy(sc_if->msk_cdata.msk_rx_ring_tag, 22872d586421SSepherosa Ziehau sc_if->msk_rdata.msk_rx_ring, 22882d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_ring_map); 22892d586421SSepherosa Ziehau 22902d586421SSepherosa Ziehau /* Tx buffers. */ 22912d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_tx_tag) { 22922d586421SSepherosa Ziehau for (i = 0; i < MSK_TX_RING_CNT; i++) { 22932d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[i]; 22942d586421SSepherosa Ziehau bus_dmamap_destroy(sc_if->msk_cdata.msk_tx_tag, 22952d586421SSepherosa Ziehau txd->tx_dmamap); 22962d586421SSepherosa Ziehau } 22972d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_tx_tag); 22982d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_tag = NULL; 22992d586421SSepherosa Ziehau } 23002d586421SSepherosa Ziehau 23012d586421SSepherosa Ziehau /* Rx buffers. */ 23022d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_rx_tag) { 23032d586421SSepherosa Ziehau for (i = 0; i < MSK_RX_RING_CNT; i++) { 23042d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[i]; 23052d586421SSepherosa Ziehau bus_dmamap_destroy(sc_if->msk_cdata.msk_rx_tag, 23062d586421SSepherosa Ziehau rxd->rx_dmamap); 23072d586421SSepherosa Ziehau } 23082d586421SSepherosa Ziehau bus_dmamap_destroy(sc_if->msk_cdata.msk_rx_tag, 23092d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_sparemap); 23102d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_rx_tag); 23112d586421SSepherosa Ziehau sc_if->msk_cdata.msk_rx_tag = NULL; 23122d586421SSepherosa Ziehau } 23132d586421SSepherosa Ziehau 23142d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_parent_tag) { 23152d586421SSepherosa Ziehau bus_dma_tag_destroy(sc_if->msk_cdata.msk_parent_tag); 23162d586421SSepherosa Ziehau sc_if->msk_cdata.msk_parent_tag = NULL; 23172d586421SSepherosa Ziehau } 23182d586421SSepherosa Ziehau } 23192d586421SSepherosa Ziehau 23202d586421SSepherosa Ziehau #ifdef MSK_JUMBO 23212d586421SSepherosa Ziehau /* 23222d586421SSepherosa Ziehau * Allocate a jumbo buffer. 23232d586421SSepherosa Ziehau */ 23242d586421SSepherosa Ziehau static void * 23252d586421SSepherosa Ziehau msk_jalloc(struct msk_if_softc *sc_if) 23262d586421SSepherosa Ziehau { 23272d586421SSepherosa Ziehau struct msk_jpool_entry *entry; 23282d586421SSepherosa Ziehau 23292d586421SSepherosa Ziehau MSK_JLIST_LOCK(sc_if); 23302d586421SSepherosa Ziehau 23312d586421SSepherosa Ziehau entry = SLIST_FIRST(&sc_if->msk_jfree_listhead); 23322d586421SSepherosa Ziehau 23332d586421SSepherosa Ziehau if (entry == NULL) { 23342d586421SSepherosa Ziehau MSK_JLIST_UNLOCK(sc_if); 23352d586421SSepherosa Ziehau return (NULL); 23362d586421SSepherosa Ziehau } 23372d586421SSepherosa Ziehau 23382d586421SSepherosa Ziehau SLIST_REMOVE_HEAD(&sc_if->msk_jfree_listhead, jpool_entries); 23392d586421SSepherosa Ziehau SLIST_INSERT_HEAD(&sc_if->msk_jinuse_listhead, entry, jpool_entries); 23402d586421SSepherosa Ziehau 23412d586421SSepherosa Ziehau MSK_JLIST_UNLOCK(sc_if); 23422d586421SSepherosa Ziehau 23432d586421SSepherosa Ziehau return (sc_if->msk_cdata.msk_jslots[entry->slot]); 23442d586421SSepherosa Ziehau } 23452d586421SSepherosa Ziehau 23462d586421SSepherosa Ziehau /* 23472d586421SSepherosa Ziehau * Release a jumbo buffer. 23482d586421SSepherosa Ziehau */ 23492d586421SSepherosa Ziehau static void 23502d586421SSepherosa Ziehau msk_jfree(void *buf, void *args) 23512d586421SSepherosa Ziehau { 23522d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 23532d586421SSepherosa Ziehau struct msk_jpool_entry *entry; 23542d586421SSepherosa Ziehau int i; 23552d586421SSepherosa Ziehau 23562d586421SSepherosa Ziehau /* Extract the softc struct pointer. */ 23572d586421SSepherosa Ziehau sc_if = (struct msk_if_softc *)args; 23582d586421SSepherosa Ziehau KASSERT(sc_if != NULL, ("%s: can't find softc pointer!", __func__)); 23592d586421SSepherosa Ziehau 23602d586421SSepherosa Ziehau MSK_JLIST_LOCK(sc_if); 23612d586421SSepherosa Ziehau /* Calculate the slot this buffer belongs to. */ 23622d586421SSepherosa Ziehau i = ((vm_offset_t)buf 23632d586421SSepherosa Ziehau - (vm_offset_t)sc_if->msk_rdata.msk_jumbo_buf) / MSK_JLEN; 23642d586421SSepherosa Ziehau KASSERT(i >= 0 && i < MSK_JSLOTS, 23652d586421SSepherosa Ziehau ("%s: asked to free buffer that we don't manage!", __func__)); 23662d586421SSepherosa Ziehau 23672d586421SSepherosa Ziehau entry = SLIST_FIRST(&sc_if->msk_jinuse_listhead); 23682d586421SSepherosa Ziehau KASSERT(entry != NULL, ("%s: buffer not in use!", __func__)); 23692d586421SSepherosa Ziehau entry->slot = i; 23702d586421SSepherosa Ziehau SLIST_REMOVE_HEAD(&sc_if->msk_jinuse_listhead, jpool_entries); 23712d586421SSepherosa Ziehau SLIST_INSERT_HEAD(&sc_if->msk_jfree_listhead, entry, jpool_entries); 23722d586421SSepherosa Ziehau if (SLIST_EMPTY(&sc_if->msk_jinuse_listhead)) 23732d586421SSepherosa Ziehau wakeup(sc_if); 23742d586421SSepherosa Ziehau 23752d586421SSepherosa Ziehau MSK_JLIST_UNLOCK(sc_if); 23762d586421SSepherosa Ziehau } 23772d586421SSepherosa Ziehau #endif 23782d586421SSepherosa Ziehau 23792d586421SSepherosa Ziehau static int 23802d586421SSepherosa Ziehau msk_encap(struct msk_if_softc *sc_if, struct mbuf **m_head) 23812d586421SSepherosa Ziehau { 23822d586421SSepherosa Ziehau struct msk_txdesc *txd, *txd_last; 23832d586421SSepherosa Ziehau struct msk_tx_desc *tx_le; 23842d586421SSepherosa Ziehau struct mbuf *m; 23852d586421SSepherosa Ziehau bus_dmamap_t map; 23862d586421SSepherosa Ziehau bus_dma_segment_t txsegs[MSK_MAXTXSEGS]; 23872d586421SSepherosa Ziehau uint32_t control, prod, si; 23882d586421SSepherosa Ziehau uint16_t offset, tcp_offset; 23895bda51d4SSepherosa Ziehau int error, i, nsegs, maxsegs, defrag; 2390def0e148SSepherosa Ziehau 2391def0e148SSepherosa Ziehau maxsegs = MSK_TX_RING_CNT - sc_if->msk_cdata.msk_tx_cnt - 2392def0e148SSepherosa Ziehau MSK_RESERVED_TX_DESC_CNT; 2393def0e148SSepherosa Ziehau KASSERT(maxsegs >= MSK_SPARE_TX_DESC_CNT, 2394ed20d0e3SSascha Wildner ("not enough spare TX desc")); 2395def0e148SSepherosa Ziehau if (maxsegs > MSK_MAXTXSEGS) 2396def0e148SSepherosa Ziehau maxsegs = MSK_MAXTXSEGS; 23972d586421SSepherosa Ziehau 23985bda51d4SSepherosa Ziehau /* 2399e71dee4bSSepherosa Ziehau * Align TX buffer to 64bytes boundary. This greately improves 24005bda51d4SSepherosa Ziehau * bulk data TX performance on my 88E8053 (+100Mbps) at least. 24015bda51d4SSepherosa Ziehau * Try avoiding m_defrag(), if the mbufs are not chained together 24025bda51d4SSepherosa Ziehau * by m_next (i.e. m->m_len == m->m_pkthdr.len). 24035bda51d4SSepherosa Ziehau */ 24045bda51d4SSepherosa Ziehau 2405e71dee4bSSepherosa Ziehau #define MSK_TXBUF_ALIGN 64 24065bda51d4SSepherosa Ziehau #define MSK_TXBUF_MASK (MSK_TXBUF_ALIGN - 1) 24075bda51d4SSepherosa Ziehau 24085bda51d4SSepherosa Ziehau defrag = 1; 24092d586421SSepherosa Ziehau m = *m_head; 24105bda51d4SSepherosa Ziehau if (m->m_len == m->m_pkthdr.len) { 24115bda51d4SSepherosa Ziehau int space; 24125bda51d4SSepherosa Ziehau 24135bda51d4SSepherosa Ziehau space = ((uintptr_t)m->m_data & MSK_TXBUF_MASK); 24145bda51d4SSepherosa Ziehau if (space) { 24155bda51d4SSepherosa Ziehau if (M_WRITABLE(m)) { 24165bda51d4SSepherosa Ziehau if (M_TRAILINGSPACE(m) >= space) { 24175bda51d4SSepherosa Ziehau /* e.g. TCP ACKs */ 24185bda51d4SSepherosa Ziehau bcopy(m->m_data, m->m_data + space, 24195bda51d4SSepherosa Ziehau m->m_len); 24205bda51d4SSepherosa Ziehau m->m_data += space; 24215bda51d4SSepherosa Ziehau defrag = 0; 24225bda51d4SSepherosa Ziehau sc_if->msk_softc->msk_trailing_copied++; 24235bda51d4SSepherosa Ziehau } else { 24245bda51d4SSepherosa Ziehau space = MSK_TXBUF_ALIGN - space; 24255bda51d4SSepherosa Ziehau if (M_LEADINGSPACE(m) >= space) { 24265bda51d4SSepherosa Ziehau /* e.g. Small UDP datagrams */ 24275bda51d4SSepherosa Ziehau bcopy(m->m_data, 24285bda51d4SSepherosa Ziehau m->m_data - space, 24295bda51d4SSepherosa Ziehau m->m_len); 24305bda51d4SSepherosa Ziehau m->m_data -= space; 24315bda51d4SSepherosa Ziehau defrag = 0; 24325bda51d4SSepherosa Ziehau sc_if->msk_softc-> 24335bda51d4SSepherosa Ziehau msk_leading_copied++; 24345bda51d4SSepherosa Ziehau } 24355bda51d4SSepherosa Ziehau } 24365bda51d4SSepherosa Ziehau } 24375bda51d4SSepherosa Ziehau } else { 24385bda51d4SSepherosa Ziehau /* e.g. on forwarding path */ 24395bda51d4SSepherosa Ziehau defrag = 0; 24405bda51d4SSepherosa Ziehau } 24415bda51d4SSepherosa Ziehau } 24425bda51d4SSepherosa Ziehau if (defrag) { 24435bda51d4SSepherosa Ziehau m = m_defrag(*m_head, MB_DONTWAIT); 24445bda51d4SSepherosa Ziehau if (m == NULL) { 24455bda51d4SSepherosa Ziehau m_freem(*m_head); 24465bda51d4SSepherosa Ziehau *m_head = NULL; 24475bda51d4SSepherosa Ziehau return ENOBUFS; 24485bda51d4SSepherosa Ziehau } 24495bda51d4SSepherosa Ziehau *m_head = m; 24505bda51d4SSepherosa Ziehau } else { 24515bda51d4SSepherosa Ziehau sc_if->msk_softc->msk_defrag_avoided++; 24525bda51d4SSepherosa Ziehau } 24535bda51d4SSepherosa Ziehau 24545bda51d4SSepherosa Ziehau #undef MSK_TXBUF_MASK 24555bda51d4SSepherosa Ziehau #undef MSK_TXBUF_ALIGN 24565bda51d4SSepherosa Ziehau 24575bda51d4SSepherosa Ziehau tcp_offset = offset = 0; 24582d586421SSepherosa Ziehau if (m->m_pkthdr.csum_flags & MSK_CSUM_FEATURES) { 24592d586421SSepherosa Ziehau /* 24602d586421SSepherosa Ziehau * Since mbuf has no protocol specific structure information 24612d586421SSepherosa Ziehau * in it we have to inspect protocol information here to 24622d586421SSepherosa Ziehau * setup TSO and checksum offload. I don't know why Marvell 24632d586421SSepherosa Ziehau * made a such decision in chip design because other GigE 24642d586421SSepherosa Ziehau * hardwares normally takes care of all these chores in 24652d586421SSepherosa Ziehau * hardware. However, TSO performance of Yukon II is very 24662d586421SSepherosa Ziehau * good such that it's worth to implement it. 24672d586421SSepherosa Ziehau */ 24682d586421SSepherosa Ziehau struct ether_header *eh; 24692d586421SSepherosa Ziehau struct ip *ip; 24702d586421SSepherosa Ziehau 24712d586421SSepherosa Ziehau /* TODO check for M_WRITABLE(m) */ 24722d586421SSepherosa Ziehau 24732d586421SSepherosa Ziehau offset = sizeof(struct ether_header); 24742d586421SSepherosa Ziehau m = m_pullup(m, offset); 24752d586421SSepherosa Ziehau if (m == NULL) { 24762d586421SSepherosa Ziehau *m_head = NULL; 24772d586421SSepherosa Ziehau return (ENOBUFS); 24782d586421SSepherosa Ziehau } 24792d586421SSepherosa Ziehau eh = mtod(m, struct ether_header *); 24802d586421SSepherosa Ziehau /* Check if hardware VLAN insertion is off. */ 24812d586421SSepherosa Ziehau if (eh->ether_type == htons(ETHERTYPE_VLAN)) { 24822d586421SSepherosa Ziehau offset = sizeof(struct ether_vlan_header); 24832d586421SSepherosa Ziehau m = m_pullup(m, offset); 24842d586421SSepherosa Ziehau if (m == NULL) { 24852d586421SSepherosa Ziehau *m_head = NULL; 24862d586421SSepherosa Ziehau return (ENOBUFS); 24872d586421SSepherosa Ziehau } 24882d586421SSepherosa Ziehau } 24892d586421SSepherosa Ziehau m = m_pullup(m, offset + sizeof(struct ip)); 24902d586421SSepherosa Ziehau if (m == NULL) { 24912d586421SSepherosa Ziehau *m_head = NULL; 24922d586421SSepherosa Ziehau return (ENOBUFS); 24932d586421SSepherosa Ziehau } 24942d586421SSepherosa Ziehau ip = (struct ip *)(mtod(m, char *) + offset); 24952d586421SSepherosa Ziehau offset += (ip->ip_hl << 2); 24962d586421SSepherosa Ziehau tcp_offset = offset; 24972d586421SSepherosa Ziehau /* 24982d586421SSepherosa Ziehau * It seems that Yukon II has Tx checksum offload bug for 24992d586421SSepherosa Ziehau * small TCP packets that's less than 60 bytes in size 25002d586421SSepherosa Ziehau * (e.g. TCP window probe packet, pure ACK packet). 25012d586421SSepherosa Ziehau * Common work around like padding with zeros to make the 25022d586421SSepherosa Ziehau * frame minimum ethernet frame size didn't work at all. 25032d586421SSepherosa Ziehau * Instead of disabling checksum offload completely we 25042d586421SSepherosa Ziehau * resort to S/W checksum routine when we encounter short 25052d586421SSepherosa Ziehau * TCP frames. 25062d586421SSepherosa Ziehau * Short UDP packets appear to be handled correctly by 25072d586421SSepherosa Ziehau * Yukon II. 25082d586421SSepherosa Ziehau */ 25092d586421SSepherosa Ziehau if (m->m_pkthdr.len < MSK_MIN_FRAMELEN && 25102d586421SSepherosa Ziehau (m->m_pkthdr.csum_flags & CSUM_TCP) != 0) { 25112d586421SSepherosa Ziehau uint16_t csum; 25122d586421SSepherosa Ziehau 25132d586421SSepherosa Ziehau csum = in_cksum_skip(m, ntohs(ip->ip_len) + offset - 25142d586421SSepherosa Ziehau (ip->ip_hl << 2), offset); 25152d586421SSepherosa Ziehau *(uint16_t *)(m->m_data + offset + 25162d586421SSepherosa Ziehau m->m_pkthdr.csum_data) = csum; 25172d586421SSepherosa Ziehau m->m_pkthdr.csum_flags &= ~CSUM_TCP; 25182d586421SSepherosa Ziehau } 25192d586421SSepherosa Ziehau *m_head = m; 25202d586421SSepherosa Ziehau } 25212d586421SSepherosa Ziehau 25222d586421SSepherosa Ziehau prod = sc_if->msk_cdata.msk_tx_prod; 25232d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[prod]; 25242d586421SSepherosa Ziehau txd_last = txd; 25252d586421SSepherosa Ziehau map = txd->tx_dmamap; 2526def0e148SSepherosa Ziehau 2527def0e148SSepherosa Ziehau error = bus_dmamap_load_mbuf_defrag(sc_if->msk_cdata.msk_tx_tag, map, 2528def0e148SSepherosa Ziehau m_head, txsegs, maxsegs, &nsegs, BUS_DMA_NOWAIT); 2529def0e148SSepherosa Ziehau if (error) { 25302d586421SSepherosa Ziehau m_freem(*m_head); 25312d586421SSepherosa Ziehau *m_head = NULL; 2532def0e148SSepherosa Ziehau return error; 25332d586421SSepherosa Ziehau } 2534def0e148SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_tx_tag, map, BUS_DMASYNC_PREWRITE); 25352d586421SSepherosa Ziehau 2536def0e148SSepherosa Ziehau m = *m_head; 25372d586421SSepherosa Ziehau control = 0; 25382d586421SSepherosa Ziehau tx_le = NULL; 25392d586421SSepherosa Ziehau 25402d586421SSepherosa Ziehau #ifdef notyet 25412d586421SSepherosa Ziehau /* Check if we have a VLAN tag to insert. */ 25422d586421SSepherosa Ziehau if ((m->m_flags & M_VLANTAG) != 0) { 25432d586421SSepherosa Ziehau tx_le = &sc_if->msk_rdata.msk_tx_ring[prod]; 25442d586421SSepherosa Ziehau tx_le->msk_addr = htole32(0); 25452d586421SSepherosa Ziehau tx_le->msk_control = htole32(OP_VLAN | HW_OWNER | 25462d586421SSepherosa Ziehau htons(m->m_pkthdr.ether_vtag)); 25472d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cnt++; 25482d586421SSepherosa Ziehau MSK_INC(prod, MSK_TX_RING_CNT); 25492d586421SSepherosa Ziehau control |= INS_VLAN; 25502d586421SSepherosa Ziehau } 25512d586421SSepherosa Ziehau #endif 25522d586421SSepherosa Ziehau /* Check if we have to handle checksum offload. */ 25532d586421SSepherosa Ziehau if (m->m_pkthdr.csum_flags & MSK_CSUM_FEATURES) { 25542d586421SSepherosa Ziehau tx_le = &sc_if->msk_rdata.msk_tx_ring[prod]; 25552d586421SSepherosa Ziehau tx_le->msk_addr = htole32(((tcp_offset + m->m_pkthdr.csum_data) 25562d586421SSepherosa Ziehau & 0xffff) | ((uint32_t)tcp_offset << 16)); 25572d586421SSepherosa Ziehau tx_le->msk_control = htole32(1 << 16 | (OP_TCPLISW | HW_OWNER)); 25582d586421SSepherosa Ziehau control = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; 25592d586421SSepherosa Ziehau if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0) 25602d586421SSepherosa Ziehau control |= UDPTCP; 25612d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cnt++; 25622d586421SSepherosa Ziehau MSK_INC(prod, MSK_TX_RING_CNT); 25632d586421SSepherosa Ziehau } 25642d586421SSepherosa Ziehau 25652d586421SSepherosa Ziehau si = prod; 25662d586421SSepherosa Ziehau tx_le = &sc_if->msk_rdata.msk_tx_ring[prod]; 25672d586421SSepherosa Ziehau tx_le->msk_addr = htole32(MSK_ADDR_LO(txsegs[0].ds_addr)); 25682d586421SSepherosa Ziehau tx_le->msk_control = htole32(txsegs[0].ds_len | control | 25692d586421SSepherosa Ziehau OP_PACKET); 25702d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cnt++; 25712d586421SSepherosa Ziehau MSK_INC(prod, MSK_TX_RING_CNT); 25722d586421SSepherosa Ziehau 2573def0e148SSepherosa Ziehau for (i = 1; i < nsegs; i++) { 25742d586421SSepherosa Ziehau tx_le = &sc_if->msk_rdata.msk_tx_ring[prod]; 25752d586421SSepherosa Ziehau tx_le->msk_addr = htole32(MSK_ADDR_LO(txsegs[i].ds_addr)); 25762d586421SSepherosa Ziehau tx_le->msk_control = htole32(txsegs[i].ds_len | control | 25772d586421SSepherosa Ziehau OP_BUFFER | HW_OWNER); 25782d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cnt++; 25792d586421SSepherosa Ziehau MSK_INC(prod, MSK_TX_RING_CNT); 25802d586421SSepherosa Ziehau } 25812d586421SSepherosa Ziehau /* Update producer index. */ 25822d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_prod = prod; 25832d586421SSepherosa Ziehau 25842d586421SSepherosa Ziehau /* Set EOP on the last desciptor. */ 25852d586421SSepherosa Ziehau prod = (prod + MSK_TX_RING_CNT - 1) % MSK_TX_RING_CNT; 25862d586421SSepherosa Ziehau tx_le = &sc_if->msk_rdata.msk_tx_ring[prod]; 25872d586421SSepherosa Ziehau tx_le->msk_control |= htole32(EOP); 25882d586421SSepherosa Ziehau 25892d586421SSepherosa Ziehau /* Turn the first descriptor ownership to hardware. */ 25902d586421SSepherosa Ziehau tx_le = &sc_if->msk_rdata.msk_tx_ring[si]; 25912d586421SSepherosa Ziehau tx_le->msk_control |= htole32(HW_OWNER); 25922d586421SSepherosa Ziehau 25932d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[prod]; 25942d586421SSepherosa Ziehau map = txd_last->tx_dmamap; 25952d586421SSepherosa Ziehau txd_last->tx_dmamap = txd->tx_dmamap; 25962d586421SSepherosa Ziehau txd->tx_dmamap = map; 25972d586421SSepherosa Ziehau txd->tx_m = m; 25982d586421SSepherosa Ziehau 25992d586421SSepherosa Ziehau return (0); 26002d586421SSepherosa Ziehau } 26012d586421SSepherosa Ziehau 26022d586421SSepherosa Ziehau static void 26032d586421SSepherosa Ziehau msk_start(struct ifnet *ifp) 26042d586421SSepherosa Ziehau { 26052d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 26062d586421SSepherosa Ziehau struct mbuf *m_head; 26072d586421SSepherosa Ziehau int enq; 26082d586421SSepherosa Ziehau 26092d586421SSepherosa Ziehau sc_if = ifp->if_softc; 26102d586421SSepherosa Ziehau 26112d586421SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 26122d586421SSepherosa Ziehau 26139db4b353SSepherosa Ziehau if (!sc_if->msk_link) { 26149db4b353SSepherosa Ziehau ifq_purge(&ifp->if_snd); 26159db4b353SSepherosa Ziehau return; 26169db4b353SSepherosa Ziehau } 26179db4b353SSepherosa Ziehau 2618*9ed293e0SSepherosa Ziehau if ((ifp->if_flags & IFF_RUNNING) == 0 || ifq_is_oactive(&ifp->if_snd)) 26192d586421SSepherosa Ziehau return; 26202d586421SSepherosa Ziehau 2621def0e148SSepherosa Ziehau enq = 0; 2622def0e148SSepherosa Ziehau while (!ifq_is_empty(&ifp->if_snd)) { 2623def0e148SSepherosa Ziehau if (MSK_IS_OACTIVE(sc_if)) { 2624*9ed293e0SSepherosa Ziehau ifq_set_oactive(&ifp->if_snd); 2625def0e148SSepherosa Ziehau break; 2626def0e148SSepherosa Ziehau } 2627def0e148SSepherosa Ziehau 26282d586421SSepherosa Ziehau m_head = ifq_dequeue(&ifp->if_snd, NULL); 26292d586421SSepherosa Ziehau if (m_head == NULL) 26302d586421SSepherosa Ziehau break; 26312d586421SSepherosa Ziehau 26322d586421SSepherosa Ziehau /* 26332d586421SSepherosa Ziehau * Pack the data into the transmit ring. If we 26342d586421SSepherosa Ziehau * don't have room, set the OACTIVE flag and wait 26352d586421SSepherosa Ziehau * for the NIC to drain the ring. 26362d586421SSepherosa Ziehau */ 26372d586421SSepherosa Ziehau if (msk_encap(sc_if, &m_head) != 0) { 26385bda51d4SSepherosa Ziehau ifp->if_oerrors++; 2639def0e148SSepherosa Ziehau if (sc_if->msk_cdata.msk_tx_cnt == 0) { 2640def0e148SSepherosa Ziehau continue; 2641def0e148SSepherosa Ziehau } else { 2642*9ed293e0SSepherosa Ziehau ifq_set_oactive(&ifp->if_snd); 26432d586421SSepherosa Ziehau break; 26442d586421SSepherosa Ziehau } 2645def0e148SSepherosa Ziehau } 2646def0e148SSepherosa Ziehau enq = 1; 26472d586421SSepherosa Ziehau 26482d586421SSepherosa Ziehau /* 26492d586421SSepherosa Ziehau * If there's a BPF listener, bounce a copy of this frame 26502d586421SSepherosa Ziehau * to him. 26512d586421SSepherosa Ziehau */ 26522d586421SSepherosa Ziehau BPF_MTAP(ifp, m_head); 26532d586421SSepherosa Ziehau } 26542d586421SSepherosa Ziehau 2655def0e148SSepherosa Ziehau if (enq) { 26562d586421SSepherosa Ziehau /* Transmit */ 26572d586421SSepherosa Ziehau CSR_WRITE_2(sc_if->msk_softc, 26582d586421SSepherosa Ziehau Y2_PREF_Q_ADDR(sc_if->msk_txq, PREF_UNIT_PUT_IDX_REG), 26592d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_prod); 26602d586421SSepherosa Ziehau 26612d586421SSepherosa Ziehau /* Set a timeout in case the chip goes out to lunch. */ 26622d586421SSepherosa Ziehau ifp->if_timer = MSK_TX_TIMEOUT; 26632d586421SSepherosa Ziehau } 26642d586421SSepherosa Ziehau } 26652d586421SSepherosa Ziehau 26662d586421SSepherosa Ziehau static void 26672d586421SSepherosa Ziehau msk_watchdog(struct ifnet *ifp) 26682d586421SSepherosa Ziehau { 26692d586421SSepherosa Ziehau struct msk_if_softc *sc_if = ifp->if_softc; 26702d586421SSepherosa Ziehau uint32_t ridx; 26712d586421SSepherosa Ziehau int idx; 26722d586421SSepherosa Ziehau 26732d586421SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 26742d586421SSepherosa Ziehau 26752d586421SSepherosa Ziehau if (sc_if->msk_link == 0) { 26762d586421SSepherosa Ziehau if (bootverbose) 26772d586421SSepherosa Ziehau if_printf(sc_if->msk_ifp, "watchdog timeout " 26782d586421SSepherosa Ziehau "(missed link)\n"); 26792d586421SSepherosa Ziehau ifp->if_oerrors++; 26802d586421SSepherosa Ziehau msk_init(sc_if); 26812d586421SSepherosa Ziehau return; 26822d586421SSepherosa Ziehau } 26832d586421SSepherosa Ziehau 26842d586421SSepherosa Ziehau /* 26852d586421SSepherosa Ziehau * Reclaim first as there is a possibility of losing Tx completion 26862d586421SSepherosa Ziehau * interrupts. 26872d586421SSepherosa Ziehau */ 26882d586421SSepherosa Ziehau ridx = sc_if->msk_port == MSK_PORT_A ? STAT_TXA1_RIDX : STAT_TXA2_RIDX; 26892d586421SSepherosa Ziehau idx = CSR_READ_2(sc_if->msk_softc, ridx); 26902d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_tx_cons != idx) { 26912d586421SSepherosa Ziehau msk_txeof(sc_if, idx); 26922d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_tx_cnt == 0) { 26932d586421SSepherosa Ziehau if_printf(ifp, "watchdog timeout (missed Tx interrupts) " 26942d586421SSepherosa Ziehau "-- recovering\n"); 26952d586421SSepherosa Ziehau if (!ifq_is_empty(&ifp->if_snd)) 26969db4b353SSepherosa Ziehau if_devstart(ifp); 26972d586421SSepherosa Ziehau return; 26982d586421SSepherosa Ziehau } 26992d586421SSepherosa Ziehau } 27002d586421SSepherosa Ziehau 27012d586421SSepherosa Ziehau if_printf(ifp, "watchdog timeout\n"); 27022d586421SSepherosa Ziehau ifp->if_oerrors++; 27032d586421SSepherosa Ziehau msk_init(sc_if); 27042d586421SSepherosa Ziehau if (!ifq_is_empty(&ifp->if_snd)) 27059db4b353SSepherosa Ziehau if_devstart(ifp); 27062d586421SSepherosa Ziehau } 27072d586421SSepherosa Ziehau 27082d586421SSepherosa Ziehau static int 27092d586421SSepherosa Ziehau mskc_shutdown(device_t dev) 27102d586421SSepherosa Ziehau { 27112d586421SSepherosa Ziehau struct msk_softc *sc = device_get_softc(dev); 27122d586421SSepherosa Ziehau int i; 27132d586421SSepherosa Ziehau 27142d586421SSepherosa Ziehau lwkt_serialize_enter(&sc->msk_serializer); 27152d586421SSepherosa Ziehau 27162d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; i++) { 27172d586421SSepherosa Ziehau if (sc->msk_if[i] != NULL) 27182d586421SSepherosa Ziehau msk_stop(sc->msk_if[i]); 27192d586421SSepherosa Ziehau } 27202d586421SSepherosa Ziehau 27212d586421SSepherosa Ziehau /* Put hardware reset. */ 27222d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_SET); 27232d586421SSepherosa Ziehau 27242d586421SSepherosa Ziehau lwkt_serialize_exit(&sc->msk_serializer); 27252d586421SSepherosa Ziehau return (0); 27262d586421SSepherosa Ziehau } 27272d586421SSepherosa Ziehau 27282d586421SSepherosa Ziehau static int 27292d586421SSepherosa Ziehau mskc_suspend(device_t dev) 27302d586421SSepherosa Ziehau { 27312d586421SSepherosa Ziehau struct msk_softc *sc = device_get_softc(dev); 27322d586421SSepherosa Ziehau int i; 27332d586421SSepherosa Ziehau 27342d586421SSepherosa Ziehau lwkt_serialize_enter(&sc->msk_serializer); 27352d586421SSepherosa Ziehau 27362d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; i++) { 27372d586421SSepherosa Ziehau if (sc->msk_if[i] != NULL && sc->msk_if[i]->msk_ifp != NULL && 27382d586421SSepherosa Ziehau ((sc->msk_if[i]->msk_ifp->if_flags & IFF_RUNNING) != 0)) 27392d586421SSepherosa Ziehau msk_stop(sc->msk_if[i]); 27402d586421SSepherosa Ziehau } 27412d586421SSepherosa Ziehau 27422d586421SSepherosa Ziehau /* Disable all interrupts. */ 27432d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, 0); 27442d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 27452d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_HWE_IMSK, 0); 27462d586421SSepherosa Ziehau CSR_READ_4(sc, B0_HWE_IMSK); 27472d586421SSepherosa Ziehau 27482d586421SSepherosa Ziehau mskc_phy_power(sc, MSK_PHY_POWERDOWN); 27492d586421SSepherosa Ziehau 27502d586421SSepherosa Ziehau /* Put hardware reset. */ 27512d586421SSepherosa Ziehau CSR_WRITE_2(sc, B0_CTST, CS_RST_SET); 27522d586421SSepherosa Ziehau sc->msk_suspended = 1; 27532d586421SSepherosa Ziehau 27542d586421SSepherosa Ziehau lwkt_serialize_exit(&sc->msk_serializer); 27552d586421SSepherosa Ziehau 27562d586421SSepherosa Ziehau return (0); 27572d586421SSepherosa Ziehau } 27582d586421SSepherosa Ziehau 27592d586421SSepherosa Ziehau static int 27602d586421SSepherosa Ziehau mskc_resume(device_t dev) 27612d586421SSepherosa Ziehau { 27622d586421SSepherosa Ziehau struct msk_softc *sc = device_get_softc(dev); 27632d586421SSepherosa Ziehau int i; 27642d586421SSepherosa Ziehau 27652d586421SSepherosa Ziehau lwkt_serialize_enter(&sc->msk_serializer); 27662d586421SSepherosa Ziehau 276760ad6a1fSSepherosa Ziehau /* Enable all clocks before accessing any registers. */ 276860ad6a1fSSepherosa Ziehau CSR_PCI_WRITE_4(sc, PCI_OUR_REG_3, 0); 27692d586421SSepherosa Ziehau mskc_reset(sc); 27702d586421SSepherosa Ziehau for (i = 0; i < sc->msk_num_port; i++) { 27712d586421SSepherosa Ziehau if (sc->msk_if[i] != NULL && sc->msk_if[i]->msk_ifp != NULL && 27722d586421SSepherosa Ziehau ((sc->msk_if[i]->msk_ifp->if_flags & IFF_UP) != 0)) 27732d586421SSepherosa Ziehau msk_init(sc->msk_if[i]); 27742d586421SSepherosa Ziehau } 27752d586421SSepherosa Ziehau sc->msk_suspended = 0; 27762d586421SSepherosa Ziehau 27772d586421SSepherosa Ziehau lwkt_serialize_exit(&sc->msk_serializer); 27782d586421SSepherosa Ziehau 27792d586421SSepherosa Ziehau return (0); 27802d586421SSepherosa Ziehau } 27812d586421SSepherosa Ziehau 27822d586421SSepherosa Ziehau static void 2783eda7db08SSepherosa Ziehau msk_rxeof(struct msk_if_softc *sc_if, uint32_t status, int len) 27842d586421SSepherosa Ziehau { 27852d586421SSepherosa Ziehau struct mbuf *m; 27862d586421SSepherosa Ziehau struct ifnet *ifp; 27872d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 27882d586421SSepherosa Ziehau int cons, rxlen; 27892d586421SSepherosa Ziehau 27902d586421SSepherosa Ziehau ifp = sc_if->msk_ifp; 27912d586421SSepherosa Ziehau 27922d586421SSepherosa Ziehau cons = sc_if->msk_cdata.msk_rx_cons; 27932d586421SSepherosa Ziehau do { 27942d586421SSepherosa Ziehau rxlen = status >> 16; 27952d586421SSepherosa Ziehau if ((status & GMR_FS_VLAN) != 0 && 27962d586421SSepherosa Ziehau (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) 27972d586421SSepherosa Ziehau rxlen -= EVL_ENCAPLEN; 2798080bd27eSSepherosa Ziehau if (sc_if->msk_flags & MSK_FLAG_NORXCHK) { 2799080bd27eSSepherosa Ziehau /* 2800080bd27eSSepherosa Ziehau * For controllers that returns bogus status code 2801080bd27eSSepherosa Ziehau * just do minimal check and let upper stack 2802080bd27eSSepherosa Ziehau * handle this frame. 2803080bd27eSSepherosa Ziehau */ 2804080bd27eSSepherosa Ziehau if (len > MSK_MAX_FRAMELEN || len < ETHER_HDR_LEN) { 2805080bd27eSSepherosa Ziehau ifp->if_ierrors++; 2806080bd27eSSepherosa Ziehau msk_discard_rxbuf(sc_if, cons); 2807080bd27eSSepherosa Ziehau break; 2808080bd27eSSepherosa Ziehau } 2809080bd27eSSepherosa Ziehau } else if (len > sc_if->msk_framesize || 28102d586421SSepherosa Ziehau ((status & GMR_FS_ANY_ERR) != 0) || 28112d586421SSepherosa Ziehau ((status & GMR_FS_RX_OK) == 0) || (rxlen != len)) { 28122d586421SSepherosa Ziehau /* Don't count flow-control packet as errors. */ 28132d586421SSepherosa Ziehau if ((status & GMR_FS_GOOD_FC) == 0) 28142d586421SSepherosa Ziehau ifp->if_ierrors++; 28152d586421SSepherosa Ziehau msk_discard_rxbuf(sc_if, cons); 28162d586421SSepherosa Ziehau break; 28172d586421SSepherosa Ziehau } 28182d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[cons]; 28192d586421SSepherosa Ziehau m = rxd->rx_m; 28202499c577SSepherosa Ziehau if (msk_newbuf(sc_if, cons, 0) != 0) { 28212d586421SSepherosa Ziehau ifp->if_iqdrops++; 28222d586421SSepherosa Ziehau /* Reuse old buffer. */ 28232d586421SSepherosa Ziehau msk_discard_rxbuf(sc_if, cons); 28242d586421SSepherosa Ziehau break; 28252d586421SSepherosa Ziehau } 28262d586421SSepherosa Ziehau m->m_pkthdr.rcvif = ifp; 28272d586421SSepherosa Ziehau m->m_pkthdr.len = m->m_len = len; 28282d586421SSepherosa Ziehau ifp->if_ipackets++; 28292d586421SSepherosa Ziehau #ifdef notyet 28302d586421SSepherosa Ziehau /* Check for VLAN tagged packets. */ 28312d586421SSepherosa Ziehau if ((status & GMR_FS_VLAN) != 0 && 28322d586421SSepherosa Ziehau (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) { 28332d586421SSepherosa Ziehau m->m_pkthdr.ether_vtag = sc_if->msk_vtag; 28342d586421SSepherosa Ziehau m->m_flags |= M_VLANTAG; 28352d586421SSepherosa Ziehau } 28362d586421SSepherosa Ziehau #endif 28370ae155c2SSepherosa Ziehau 2838eda7db08SSepherosa Ziehau ifp->if_input(ifp, m); 28392d586421SSepherosa Ziehau } while (0); 28402d586421SSepherosa Ziehau 28412d586421SSepherosa Ziehau MSK_INC(sc_if->msk_cdata.msk_rx_cons, MSK_RX_RING_CNT); 28422d586421SSepherosa Ziehau MSK_INC(sc_if->msk_cdata.msk_rx_prod, MSK_RX_RING_CNT); 28432d586421SSepherosa Ziehau } 28442d586421SSepherosa Ziehau 28452d586421SSepherosa Ziehau #ifdef MSK_JUMBO 28462d586421SSepherosa Ziehau static void 28472d586421SSepherosa Ziehau msk_jumbo_rxeof(struct msk_if_softc *sc_if, uint32_t status, int len) 28482d586421SSepherosa Ziehau { 28492d586421SSepherosa Ziehau struct mbuf *m; 28502d586421SSepherosa Ziehau struct ifnet *ifp; 28512d586421SSepherosa Ziehau struct msk_rxdesc *jrxd; 28522d586421SSepherosa Ziehau int cons, rxlen; 28532d586421SSepherosa Ziehau 28542d586421SSepherosa Ziehau ifp = sc_if->msk_ifp; 28552d586421SSepherosa Ziehau 28562d586421SSepherosa Ziehau MSK_IF_LOCK_ASSERT(sc_if); 28572d586421SSepherosa Ziehau 28582d586421SSepherosa Ziehau cons = sc_if->msk_cdata.msk_rx_cons; 28592d586421SSepherosa Ziehau do { 28602d586421SSepherosa Ziehau rxlen = status >> 16; 28612d586421SSepherosa Ziehau if ((status & GMR_FS_VLAN) != 0 && 28622d586421SSepherosa Ziehau (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) 28632d586421SSepherosa Ziehau rxlen -= ETHER_VLAN_ENCAP_LEN; 28642d586421SSepherosa Ziehau if (len > sc_if->msk_framesize || 28652d586421SSepherosa Ziehau ((status & GMR_FS_ANY_ERR) != 0) || 28662d586421SSepherosa Ziehau ((status & GMR_FS_RX_OK) == 0) || (rxlen != len)) { 28672d586421SSepherosa Ziehau /* Don't count flow-control packet as errors. */ 28682d586421SSepherosa Ziehau if ((status & GMR_FS_GOOD_FC) == 0) 28692d586421SSepherosa Ziehau ifp->if_ierrors++; 28702d586421SSepherosa Ziehau msk_discard_jumbo_rxbuf(sc_if, cons); 28712d586421SSepherosa Ziehau break; 28722d586421SSepherosa Ziehau } 28732d586421SSepherosa Ziehau jrxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[cons]; 28742d586421SSepherosa Ziehau m = jrxd->rx_m; 28752d586421SSepherosa Ziehau if (msk_jumbo_newbuf(sc_if, cons) != 0) { 28762d586421SSepherosa Ziehau ifp->if_iqdrops++; 28772d586421SSepherosa Ziehau /* Reuse old buffer. */ 28782d586421SSepherosa Ziehau msk_discard_jumbo_rxbuf(sc_if, cons); 28792d586421SSepherosa Ziehau break; 28802d586421SSepherosa Ziehau } 28812d586421SSepherosa Ziehau m->m_pkthdr.rcvif = ifp; 28822d586421SSepherosa Ziehau m->m_pkthdr.len = m->m_len = len; 28832d586421SSepherosa Ziehau ifp->if_ipackets++; 28842d586421SSepherosa Ziehau /* Check for VLAN tagged packets. */ 28852d586421SSepherosa Ziehau if ((status & GMR_FS_VLAN) != 0 && 28862d586421SSepherosa Ziehau (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) { 28872d586421SSepherosa Ziehau m->m_pkthdr.ether_vtag = sc_if->msk_vtag; 28882d586421SSepherosa Ziehau m->m_flags |= M_VLANTAG; 28892d586421SSepherosa Ziehau } 28902d586421SSepherosa Ziehau MSK_IF_UNLOCK(sc_if); 28912d586421SSepherosa Ziehau (*ifp->if_input)(ifp, m); 28922d586421SSepherosa Ziehau MSK_IF_LOCK(sc_if); 28932d586421SSepherosa Ziehau } while (0); 28942d586421SSepherosa Ziehau 28952d586421SSepherosa Ziehau MSK_INC(sc_if->msk_cdata.msk_rx_cons, MSK_JUMBO_RX_RING_CNT); 28962d586421SSepherosa Ziehau MSK_INC(sc_if->msk_cdata.msk_rx_prod, MSK_JUMBO_RX_RING_CNT); 28972d586421SSepherosa Ziehau } 28982d586421SSepherosa Ziehau #endif 28992d586421SSepherosa Ziehau 29002d586421SSepherosa Ziehau static void 29012d586421SSepherosa Ziehau msk_txeof(struct msk_if_softc *sc_if, int idx) 29022d586421SSepherosa Ziehau { 29032d586421SSepherosa Ziehau struct msk_txdesc *txd; 29042d586421SSepherosa Ziehau struct msk_tx_desc *cur_tx; 29052d586421SSepherosa Ziehau struct ifnet *ifp; 29062d586421SSepherosa Ziehau uint32_t control; 29072d586421SSepherosa Ziehau int cons, prog; 29082d586421SSepherosa Ziehau 29092d586421SSepherosa Ziehau ifp = sc_if->msk_ifp; 29102d586421SSepherosa Ziehau 29112d586421SSepherosa Ziehau /* 29122d586421SSepherosa Ziehau * Go through our tx ring and free mbufs for those 29132d586421SSepherosa Ziehau * frames that have been sent. 29142d586421SSepherosa Ziehau */ 29152d586421SSepherosa Ziehau cons = sc_if->msk_cdata.msk_tx_cons; 29162d586421SSepherosa Ziehau prog = 0; 29172d586421SSepherosa Ziehau for (; cons != idx; MSK_INC(cons, MSK_TX_RING_CNT)) { 29182d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_tx_cnt <= 0) 29192d586421SSepherosa Ziehau break; 29202d586421SSepherosa Ziehau prog++; 29212d586421SSepherosa Ziehau cur_tx = &sc_if->msk_rdata.msk_tx_ring[cons]; 29222d586421SSepherosa Ziehau control = le32toh(cur_tx->msk_control); 29232d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cnt--; 29242d586421SSepherosa Ziehau if ((control & EOP) == 0) 29252d586421SSepherosa Ziehau continue; 29262d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[cons]; 29272d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_tx_tag, txd->tx_dmamap); 29282d586421SSepherosa Ziehau 29292d586421SSepherosa Ziehau ifp->if_opackets++; 29302d586421SSepherosa Ziehau KASSERT(txd->tx_m != NULL, ("%s: freeing NULL mbuf!", 29312d586421SSepherosa Ziehau __func__)); 29322d586421SSepherosa Ziehau m_freem(txd->tx_m); 29332d586421SSepherosa Ziehau txd->tx_m = NULL; 29342d586421SSepherosa Ziehau } 29352d586421SSepherosa Ziehau 29362d586421SSepherosa Ziehau if (prog > 0) { 29372d586421SSepherosa Ziehau sc_if->msk_cdata.msk_tx_cons = cons; 2938def0e148SSepherosa Ziehau if (!MSK_IS_OACTIVE(sc_if)) 2939*9ed293e0SSepherosa Ziehau ifq_clr_oactive(&ifp->if_snd); 29402d586421SSepherosa Ziehau if (sc_if->msk_cdata.msk_tx_cnt == 0) 29412d586421SSepherosa Ziehau ifp->if_timer = 0; 29422d586421SSepherosa Ziehau /* No need to sync LEs as we didn't update LEs. */ 29432d586421SSepherosa Ziehau } 29442d586421SSepherosa Ziehau } 29452d586421SSepherosa Ziehau 29462d586421SSepherosa Ziehau static void 29472d586421SSepherosa Ziehau msk_tick(void *xsc_if) 29482d586421SSepherosa Ziehau { 29492d586421SSepherosa Ziehau struct msk_if_softc *sc_if = xsc_if; 29502d586421SSepherosa Ziehau struct ifnet *ifp = &sc_if->arpcom.ac_if; 29512d586421SSepherosa Ziehau struct mii_data *mii; 29522d586421SSepherosa Ziehau 29532d586421SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 29542d586421SSepherosa Ziehau 29552d586421SSepherosa Ziehau mii = device_get_softc(sc_if->msk_miibus); 29562d586421SSepherosa Ziehau 29572d586421SSepherosa Ziehau mii_tick(mii); 2958cd237572SSepherosa Ziehau if (!sc_if->msk_link) 2959cd237572SSepherosa Ziehau msk_miibus_statchg(sc_if->msk_if_dev); 29602d586421SSepherosa Ziehau callout_reset(&sc_if->msk_tick_ch, hz, msk_tick, sc_if); 29612d586421SSepherosa Ziehau 29622d586421SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 29632d586421SSepherosa Ziehau } 29642d586421SSepherosa Ziehau 29652d586421SSepherosa Ziehau static void 29662d586421SSepherosa Ziehau msk_intr_phy(struct msk_if_softc *sc_if) 29672d586421SSepherosa Ziehau { 29682d586421SSepherosa Ziehau uint16_t status; 29692d586421SSepherosa Ziehau 29702d586421SSepherosa Ziehau msk_phy_readreg(sc_if, PHY_ADDR_MARV, PHY_MARV_INT_STAT); 29712d586421SSepherosa Ziehau status = msk_phy_readreg(sc_if, PHY_ADDR_MARV, PHY_MARV_INT_STAT); 29722d586421SSepherosa Ziehau /* Handle FIFO Underrun/Overflow? */ 29732d586421SSepherosa Ziehau if (status & PHY_M_IS_FIFO_ERROR) { 29742d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 29752d586421SSepherosa Ziehau "PHY FIFO underrun/overflow.\n"); 29762d586421SSepherosa Ziehau } 29772d586421SSepherosa Ziehau } 29782d586421SSepherosa Ziehau 29792d586421SSepherosa Ziehau static void 29802d586421SSepherosa Ziehau msk_intr_gmac(struct msk_if_softc *sc_if) 29812d586421SSepherosa Ziehau { 29822d586421SSepherosa Ziehau struct msk_softc *sc; 29832d586421SSepherosa Ziehau uint8_t status; 29842d586421SSepherosa Ziehau 29852d586421SSepherosa Ziehau sc = sc_if->msk_softc; 29862d586421SSepherosa Ziehau status = CSR_READ_1(sc, MR_ADDR(sc_if->msk_port, GMAC_IRQ_SRC)); 29872d586421SSepherosa Ziehau 29882d586421SSepherosa Ziehau /* GMAC Rx FIFO overrun. */ 29892d586421SSepherosa Ziehau if ((status & GM_IS_RX_FF_OR) != 0) { 29902d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), 29912d586421SSepherosa Ziehau GMF_CLI_RX_FO); 29922d586421SSepherosa Ziehau } 29932d586421SSepherosa Ziehau /* GMAC Tx FIFO underrun. */ 29942d586421SSepherosa Ziehau if ((status & GM_IS_TX_FF_UR) != 0) { 29952d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), 29962d586421SSepherosa Ziehau GMF_CLI_TX_FU); 29972d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "Tx FIFO underrun!\n"); 29982d586421SSepherosa Ziehau /* 29992d586421SSepherosa Ziehau * XXX 30002d586421SSepherosa Ziehau * In case of Tx underrun, we may need to flush/reset 30012d586421SSepherosa Ziehau * Tx MAC but that would also require resynchronization 30022d586421SSepherosa Ziehau * with status LEs. Reintializing status LEs would 30032d586421SSepherosa Ziehau * affect other port in dual MAC configuration so it 30042d586421SSepherosa Ziehau * should be avoided as possible as we can. 30052d586421SSepherosa Ziehau * Due to lack of documentation it's all vague guess but 30062d586421SSepherosa Ziehau * it needs more investigation. 30072d586421SSepherosa Ziehau */ 30082d586421SSepherosa Ziehau } 30092d586421SSepherosa Ziehau } 30102d586421SSepherosa Ziehau 30112d586421SSepherosa Ziehau static void 30122d586421SSepherosa Ziehau msk_handle_hwerr(struct msk_if_softc *sc_if, uint32_t status) 30132d586421SSepherosa Ziehau { 30142d586421SSepherosa Ziehau struct msk_softc *sc; 30152d586421SSepherosa Ziehau 30162d586421SSepherosa Ziehau sc = sc_if->msk_softc; 30172d586421SSepherosa Ziehau if ((status & Y2_IS_PAR_RD1) != 0) { 30182d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 30192d586421SSepherosa Ziehau "RAM buffer read parity error\n"); 30202d586421SSepherosa Ziehau /* Clear IRQ. */ 30212d586421SSepherosa Ziehau CSR_WRITE_2(sc, SELECT_RAM_BUFFER(sc_if->msk_port, B3_RI_CTRL), 30222d586421SSepherosa Ziehau RI_CLR_RD_PERR); 30232d586421SSepherosa Ziehau } 30242d586421SSepherosa Ziehau if ((status & Y2_IS_PAR_WR1) != 0) { 30252d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 30262d586421SSepherosa Ziehau "RAM buffer write parity error\n"); 30272d586421SSepherosa Ziehau /* Clear IRQ. */ 30282d586421SSepherosa Ziehau CSR_WRITE_2(sc, SELECT_RAM_BUFFER(sc_if->msk_port, B3_RI_CTRL), 30292d586421SSepherosa Ziehau RI_CLR_WR_PERR); 30302d586421SSepherosa Ziehau } 30312d586421SSepherosa Ziehau if ((status & Y2_IS_PAR_MAC1) != 0) { 30322d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "Tx MAC parity error\n"); 30332d586421SSepherosa Ziehau /* Clear IRQ. */ 30342d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), 30352d586421SSepherosa Ziehau GMF_CLI_TX_PE); 30362d586421SSepherosa Ziehau } 30372d586421SSepherosa Ziehau if ((status & Y2_IS_PAR_RX1) != 0) { 30382d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "Rx parity error\n"); 30392d586421SSepherosa Ziehau /* Clear IRQ. */ 30402d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_CSR), BMU_CLR_IRQ_PAR); 30412d586421SSepherosa Ziehau } 30422d586421SSepherosa Ziehau if ((status & (Y2_IS_TCP_TXS1 | Y2_IS_TCP_TXA1)) != 0) { 30432d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "TCP segmentation error\n"); 30442d586421SSepherosa Ziehau /* Clear IRQ. */ 30452d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), BMU_CLR_IRQ_TCP); 30462d586421SSepherosa Ziehau } 30472d586421SSepherosa Ziehau } 30482d586421SSepherosa Ziehau 30492d586421SSepherosa Ziehau static void 30502d586421SSepherosa Ziehau mskc_intr_hwerr(struct msk_softc *sc) 30512d586421SSepherosa Ziehau { 30522d586421SSepherosa Ziehau uint32_t status; 30532d586421SSepherosa Ziehau uint32_t tlphead[4]; 30542d586421SSepherosa Ziehau 30552d586421SSepherosa Ziehau status = CSR_READ_4(sc, B0_HWE_ISRC); 30562d586421SSepherosa Ziehau /* Time Stamp timer overflow. */ 30572d586421SSepherosa Ziehau if ((status & Y2_IS_TIST_OV) != 0) 30582d586421SSepherosa Ziehau CSR_WRITE_1(sc, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ); 30592d586421SSepherosa Ziehau if ((status & Y2_IS_PCI_NEXP) != 0) { 30602d586421SSepherosa Ziehau /* 30612d586421SSepherosa Ziehau * PCI Express Error occured which is not described in PEX 30622d586421SSepherosa Ziehau * spec. 30632d586421SSepherosa Ziehau * This error is also mapped either to Master Abort( 30642d586421SSepherosa Ziehau * Y2_IS_MST_ERR) or Target Abort (Y2_IS_IRQ_STAT) bit and 30652d586421SSepherosa Ziehau * can only be cleared there. 30662d586421SSepherosa Ziehau */ 30672d586421SSepherosa Ziehau device_printf(sc->msk_dev, 30682d586421SSepherosa Ziehau "PCI Express protocol violation error\n"); 30692d586421SSepherosa Ziehau } 30702d586421SSepherosa Ziehau 30712d586421SSepherosa Ziehau if ((status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) != 0) { 30722d586421SSepherosa Ziehau uint16_t v16; 30732d586421SSepherosa Ziehau 30742d586421SSepherosa Ziehau if ((status & Y2_IS_MST_ERR) != 0) 30752d586421SSepherosa Ziehau device_printf(sc->msk_dev, 30762d586421SSepherosa Ziehau "unexpected IRQ Status error\n"); 30772d586421SSepherosa Ziehau else 30782d586421SSepherosa Ziehau device_printf(sc->msk_dev, 30792d586421SSepherosa Ziehau "unexpected IRQ Master error\n"); 30802d586421SSepherosa Ziehau /* Reset all bits in the PCI status register. */ 30812d586421SSepherosa Ziehau v16 = pci_read_config(sc->msk_dev, PCIR_STATUS, 2); 30822d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_ON); 30832d586421SSepherosa Ziehau pci_write_config(sc->msk_dev, PCIR_STATUS, v16 | 30842d586421SSepherosa Ziehau PCIM_STATUS_PERR | PCIM_STATUS_SERR | PCIM_STATUS_RMABORT | 30852d586421SSepherosa Ziehau PCIM_STATUS_RTABORT | PCIM_STATUS_PERRREPORT, 2); 30862d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_OFF); 30872d586421SSepherosa Ziehau } 30882d586421SSepherosa Ziehau 30892d586421SSepherosa Ziehau /* Check for PCI Express Uncorrectable Error. */ 30902d586421SSepherosa Ziehau if ((status & Y2_IS_PCI_EXP) != 0) { 30912d586421SSepherosa Ziehau uint32_t v32; 30922d586421SSepherosa Ziehau 30932d586421SSepherosa Ziehau /* 30942d586421SSepherosa Ziehau * On PCI Express bus bridges are called root complexes (RC). 30952d586421SSepherosa Ziehau * PCI Express errors are recognized by the root complex too, 30962d586421SSepherosa Ziehau * which requests the system to handle the problem. After 30972d586421SSepherosa Ziehau * error occurence it may be that no access to the adapter 30982d586421SSepherosa Ziehau * may be performed any longer. 30992d586421SSepherosa Ziehau */ 31002d586421SSepherosa Ziehau 31012d586421SSepherosa Ziehau v32 = CSR_PCI_READ_4(sc, PEX_UNC_ERR_STAT); 31022d586421SSepherosa Ziehau if ((v32 & PEX_UNSUP_REQ) != 0) { 31032d586421SSepherosa Ziehau /* Ignore unsupported request error. */ 31042d586421SSepherosa Ziehau if (bootverbose) { 31052d586421SSepherosa Ziehau device_printf(sc->msk_dev, 31062d586421SSepherosa Ziehau "Uncorrectable PCI Express error\n"); 31072d586421SSepherosa Ziehau } 31082d586421SSepherosa Ziehau } 31092d586421SSepherosa Ziehau if ((v32 & (PEX_FATAL_ERRORS | PEX_POIS_TLP)) != 0) { 31102d586421SSepherosa Ziehau int i; 31112d586421SSepherosa Ziehau 31122d586421SSepherosa Ziehau /* Get TLP header form Log Registers. */ 31132d586421SSepherosa Ziehau for (i = 0; i < 4; i++) 31142d586421SSepherosa Ziehau tlphead[i] = CSR_PCI_READ_4(sc, 31152d586421SSepherosa Ziehau PEX_HEADER_LOG + i * 4); 31162d586421SSepherosa Ziehau /* Check for vendor defined broadcast message. */ 31172d586421SSepherosa Ziehau if (!(tlphead[0] == 0x73004001 && tlphead[1] == 0x7f)) { 31182d586421SSepherosa Ziehau sc->msk_intrhwemask &= ~Y2_IS_PCI_EXP; 31192d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_HWE_IMSK, 31202d586421SSepherosa Ziehau sc->msk_intrhwemask); 31212d586421SSepherosa Ziehau CSR_READ_4(sc, B0_HWE_IMSK); 31222d586421SSepherosa Ziehau } 31232d586421SSepherosa Ziehau } 31242d586421SSepherosa Ziehau /* Clear the interrupt. */ 31252d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_ON); 31262d586421SSepherosa Ziehau CSR_PCI_WRITE_4(sc, PEX_UNC_ERR_STAT, 0xffffffff); 31272d586421SSepherosa Ziehau CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_OFF); 31282d586421SSepherosa Ziehau } 31292d586421SSepherosa Ziehau 31302d586421SSepherosa Ziehau if ((status & Y2_HWE_L1_MASK) != 0 && sc->msk_if[MSK_PORT_A] != NULL) 31312d586421SSepherosa Ziehau msk_handle_hwerr(sc->msk_if[MSK_PORT_A], status); 31322d586421SSepherosa Ziehau if ((status & Y2_HWE_L2_MASK) != 0 && sc->msk_if[MSK_PORT_B] != NULL) 31332d586421SSepherosa Ziehau msk_handle_hwerr(sc->msk_if[MSK_PORT_B], status >> 8); 31342d586421SSepherosa Ziehau } 31352d586421SSepherosa Ziehau 31362d586421SSepherosa Ziehau static __inline void 31372d586421SSepherosa Ziehau msk_rxput(struct msk_if_softc *sc_if) 31382d586421SSepherosa Ziehau { 31392d586421SSepherosa Ziehau struct msk_softc *sc; 31402d586421SSepherosa Ziehau 31412d586421SSepherosa Ziehau sc = sc_if->msk_softc; 31422d586421SSepherosa Ziehau #ifdef MSK_JUMBO 31432d586421SSepherosa Ziehau if (sc_if->msk_framesize > (MCLBYTES - ETHER_HDR_LEN)) { 31442d586421SSepherosa Ziehau bus_dmamap_sync( 31452d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_tag, 31462d586421SSepherosa Ziehau sc_if->msk_cdata.msk_jumbo_rx_ring_map, 31472d586421SSepherosa Ziehau BUS_DMASYNC_PREWRITE); 31482d586421SSepherosa Ziehau } 3149c78f83cbSSepherosa Ziehau #endif 31502d586421SSepherosa Ziehau CSR_WRITE_2(sc, Y2_PREF_Q_ADDR(sc_if->msk_rxq, 31512d586421SSepherosa Ziehau PREF_UNIT_PUT_IDX_REG), sc_if->msk_cdata.msk_rx_prod); 31522d586421SSepherosa Ziehau } 31532d586421SSepherosa Ziehau 31542d586421SSepherosa Ziehau static int 31552d586421SSepherosa Ziehau mskc_handle_events(struct msk_softc *sc) 31562d586421SSepherosa Ziehau { 31572d586421SSepherosa Ziehau struct msk_if_softc *sc_if; 31582d586421SSepherosa Ziehau int rxput[2]; 31592d586421SSepherosa Ziehau struct msk_stat_desc *sd; 31602d586421SSepherosa Ziehau uint32_t control, status; 31612d586421SSepherosa Ziehau int cons, idx, len, port, rxprog; 31622d586421SSepherosa Ziehau 31632d586421SSepherosa Ziehau idx = CSR_READ_2(sc, STAT_PUT_IDX); 31642d586421SSepherosa Ziehau if (idx == sc->msk_stat_cons) 31652d586421SSepherosa Ziehau return (0); 31662d586421SSepherosa Ziehau 31672d586421SSepherosa Ziehau rxput[MSK_PORT_A] = rxput[MSK_PORT_B] = 0; 31682d586421SSepherosa Ziehau 31692d586421SSepherosa Ziehau rxprog = 0; 31702d586421SSepherosa Ziehau for (cons = sc->msk_stat_cons; cons != idx;) { 31712d586421SSepherosa Ziehau sd = &sc->msk_stat_ring[cons]; 31722d586421SSepherosa Ziehau control = le32toh(sd->msk_control); 31732d586421SSepherosa Ziehau if ((control & HW_OWNER) == 0) 31742d586421SSepherosa Ziehau break; 31752d586421SSepherosa Ziehau /* 31762d586421SSepherosa Ziehau * Marvell's FreeBSD driver updates status LE after clearing 31772d586421SSepherosa Ziehau * HW_OWNER. However we don't have a way to sync single LE 31782d586421SSepherosa Ziehau * with bus_dma(9) API. bus_dma(9) provides a way to sync 31792d586421SSepherosa Ziehau * an entire DMA map. So don't sync LE until we have a better 31802d586421SSepherosa Ziehau * way to sync LEs. 31812d586421SSepherosa Ziehau */ 31822d586421SSepherosa Ziehau control &= ~HW_OWNER; 31832d586421SSepherosa Ziehau sd->msk_control = htole32(control); 31842d586421SSepherosa Ziehau status = le32toh(sd->msk_status); 31852d586421SSepherosa Ziehau len = control & STLE_LEN_MASK; 31862d586421SSepherosa Ziehau port = (control >> 16) & 0x01; 31872d586421SSepherosa Ziehau sc_if = sc->msk_if[port]; 31882d586421SSepherosa Ziehau if (sc_if == NULL) { 31892d586421SSepherosa Ziehau device_printf(sc->msk_dev, "invalid port opcode " 31902d586421SSepherosa Ziehau "0x%08x\n", control & STLE_OP_MASK); 31912d586421SSepherosa Ziehau continue; 31922d586421SSepherosa Ziehau } 31932d586421SSepherosa Ziehau 31942d586421SSepherosa Ziehau switch (control & STLE_OP_MASK) { 31952d586421SSepherosa Ziehau case OP_RXVLAN: 31962d586421SSepherosa Ziehau sc_if->msk_vtag = ntohs(len); 31972d586421SSepherosa Ziehau break; 31982d586421SSepherosa Ziehau case OP_RXCHKSVLAN: 31992d586421SSepherosa Ziehau sc_if->msk_vtag = ntohs(len); 32002d586421SSepherosa Ziehau break; 32012d586421SSepherosa Ziehau case OP_RXSTAT: 3202f308b0acSSepherosa Ziehau if ((sc_if->msk_ifp->if_flags & IFF_RUNNING) == 0) 3203f308b0acSSepherosa Ziehau break; 32042d586421SSepherosa Ziehau #ifdef MSK_JUMBO 32052d586421SSepherosa Ziehau if (sc_if->msk_framesize > (MCLBYTES - ETHER_HDR_LEN)) 32062d586421SSepherosa Ziehau msk_jumbo_rxeof(sc_if, status, len); 32072d586421SSepherosa Ziehau else 32082d586421SSepherosa Ziehau #endif 3209eda7db08SSepherosa Ziehau msk_rxeof(sc_if, status, len); 32102d586421SSepherosa Ziehau rxprog++; 32112d586421SSepherosa Ziehau /* 32122d586421SSepherosa Ziehau * Because there is no way to sync single Rx LE 32132d586421SSepherosa Ziehau * put the DMA sync operation off until the end of 32142d586421SSepherosa Ziehau * event processing. 32152d586421SSepherosa Ziehau */ 32162d586421SSepherosa Ziehau rxput[port]++; 32172d586421SSepherosa Ziehau /* Update prefetch unit if we've passed water mark. */ 32182d586421SSepherosa Ziehau if (rxput[port] >= sc_if->msk_cdata.msk_rx_putwm) { 32192d586421SSepherosa Ziehau msk_rxput(sc_if); 32202d586421SSepherosa Ziehau rxput[port] = 0; 32212d586421SSepherosa Ziehau } 32222d586421SSepherosa Ziehau break; 32232d586421SSepherosa Ziehau case OP_TXINDEXLE: 32242d586421SSepherosa Ziehau if (sc->msk_if[MSK_PORT_A] != NULL) { 32252d586421SSepherosa Ziehau msk_txeof(sc->msk_if[MSK_PORT_A], 32262d586421SSepherosa Ziehau status & STLE_TXA1_MSKL); 32272d586421SSepherosa Ziehau } 32282d586421SSepherosa Ziehau if (sc->msk_if[MSK_PORT_B] != NULL) { 32292d586421SSepherosa Ziehau msk_txeof(sc->msk_if[MSK_PORT_B], 32302d586421SSepherosa Ziehau ((status & STLE_TXA2_MSKL) >> 32312d586421SSepherosa Ziehau STLE_TXA2_SHIFTL) | 32322d586421SSepherosa Ziehau ((len & STLE_TXA2_MSKH) << 32332d586421SSepherosa Ziehau STLE_TXA2_SHIFTH)); 32342d586421SSepherosa Ziehau } 32352d586421SSepherosa Ziehau break; 32362d586421SSepherosa Ziehau default: 32372d586421SSepherosa Ziehau device_printf(sc->msk_dev, "unhandled opcode 0x%08x\n", 32382d586421SSepherosa Ziehau control & STLE_OP_MASK); 32392d586421SSepherosa Ziehau break; 32402d586421SSepherosa Ziehau } 32412d586421SSepherosa Ziehau MSK_INC(cons, MSK_STAT_RING_CNT); 32422d586421SSepherosa Ziehau if (rxprog > sc->msk_process_limit) 32432d586421SSepherosa Ziehau break; 32442d586421SSepherosa Ziehau } 32452d586421SSepherosa Ziehau 32462d586421SSepherosa Ziehau sc->msk_stat_cons = cons; 32472d586421SSepherosa Ziehau /* XXX We should sync status LEs here. See above notes. */ 32482d586421SSepherosa Ziehau 32492d586421SSepherosa Ziehau if (rxput[MSK_PORT_A] > 0) 32502d586421SSepherosa Ziehau msk_rxput(sc->msk_if[MSK_PORT_A]); 32512d586421SSepherosa Ziehau if (rxput[MSK_PORT_B] > 0) 32522d586421SSepherosa Ziehau msk_rxput(sc->msk_if[MSK_PORT_B]); 32532d586421SSepherosa Ziehau 32542d586421SSepherosa Ziehau return (sc->msk_stat_cons != CSR_READ_2(sc, STAT_PUT_IDX)); 32552d586421SSepherosa Ziehau } 32562d586421SSepherosa Ziehau 32572d586421SSepherosa Ziehau /* Legacy interrupt handler for shared interrupt. */ 32582d586421SSepherosa Ziehau static void 32592d586421SSepherosa Ziehau mskc_intr(void *xsc) 32602d586421SSepherosa Ziehau { 32612d586421SSepherosa Ziehau struct msk_softc *sc; 32622d586421SSepherosa Ziehau struct msk_if_softc *sc_if0, *sc_if1; 32632d586421SSepherosa Ziehau struct ifnet *ifp0, *ifp1; 32642d586421SSepherosa Ziehau uint32_t status; 32652d586421SSepherosa Ziehau 32662d586421SSepherosa Ziehau sc = xsc; 32672d586421SSepherosa Ziehau ASSERT_SERIALIZED(&sc->msk_serializer); 32682d586421SSepherosa Ziehau 32692d586421SSepherosa Ziehau /* Reading B0_Y2_SP_ISRC2 masks further interrupts. */ 32702d586421SSepherosa Ziehau status = CSR_READ_4(sc, B0_Y2_SP_ISRC2); 32712d586421SSepherosa Ziehau if (status == 0 || status == 0xffffffff || sc->msk_suspended != 0 || 32722d586421SSepherosa Ziehau (status & sc->msk_intrmask) == 0) { 32732d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2); 32742d586421SSepherosa Ziehau return; 32752d586421SSepherosa Ziehau } 32762d586421SSepherosa Ziehau 32772d586421SSepherosa Ziehau sc_if0 = sc->msk_if[MSK_PORT_A]; 32782d586421SSepherosa Ziehau sc_if1 = sc->msk_if[MSK_PORT_B]; 32792d586421SSepherosa Ziehau ifp0 = ifp1 = NULL; 32802d586421SSepherosa Ziehau if (sc_if0 != NULL) 32812d586421SSepherosa Ziehau ifp0 = sc_if0->msk_ifp; 32822d586421SSepherosa Ziehau if (sc_if1 != NULL) 32832d586421SSepherosa Ziehau ifp1 = sc_if1->msk_ifp; 32842d586421SSepherosa Ziehau 32852d586421SSepherosa Ziehau if ((status & Y2_IS_IRQ_PHY1) != 0 && sc_if0 != NULL) 32862d586421SSepherosa Ziehau msk_intr_phy(sc_if0); 32872d586421SSepherosa Ziehau if ((status & Y2_IS_IRQ_PHY2) != 0 && sc_if1 != NULL) 32882d586421SSepherosa Ziehau msk_intr_phy(sc_if1); 32892d586421SSepherosa Ziehau if ((status & Y2_IS_IRQ_MAC1) != 0 && sc_if0 != NULL) 32902d586421SSepherosa Ziehau msk_intr_gmac(sc_if0); 32912d586421SSepherosa Ziehau if ((status & Y2_IS_IRQ_MAC2) != 0 && sc_if1 != NULL) 32922d586421SSepherosa Ziehau msk_intr_gmac(sc_if1); 32932d586421SSepherosa Ziehau if ((status & (Y2_IS_CHK_RX1 | Y2_IS_CHK_RX2)) != 0) { 32942d586421SSepherosa Ziehau device_printf(sc->msk_dev, "Rx descriptor error\n"); 32952d586421SSepherosa Ziehau sc->msk_intrmask &= ~(Y2_IS_CHK_RX1 | Y2_IS_CHK_RX2); 32962d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, sc->msk_intrmask); 32972d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 32982d586421SSepherosa Ziehau } 32992d586421SSepherosa Ziehau if ((status & (Y2_IS_CHK_TXA1 | Y2_IS_CHK_TXA2)) != 0) { 33002d586421SSepherosa Ziehau device_printf(sc->msk_dev, "Tx descriptor error\n"); 33012d586421SSepherosa Ziehau sc->msk_intrmask &= ~(Y2_IS_CHK_TXA1 | Y2_IS_CHK_TXA2); 33022d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, sc->msk_intrmask); 33032d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 33042d586421SSepherosa Ziehau } 33052d586421SSepherosa Ziehau if ((status & Y2_IS_HW_ERR) != 0) 33062d586421SSepherosa Ziehau mskc_intr_hwerr(sc); 33072d586421SSepherosa Ziehau 33082d586421SSepherosa Ziehau while (mskc_handle_events(sc) != 0) 33092d586421SSepherosa Ziehau ; 33102d586421SSepherosa Ziehau if ((status & Y2_IS_STAT_BMU) != 0) 33112d586421SSepherosa Ziehau CSR_WRITE_4(sc, STAT_CTRL, SC_STAT_CLR_IRQ); 33122d586421SSepherosa Ziehau 33132d586421SSepherosa Ziehau /* Reenable interrupts. */ 33142d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2); 33152d586421SSepherosa Ziehau 33162d586421SSepherosa Ziehau if (ifp0 != NULL && (ifp0->if_flags & IFF_RUNNING) != 0 && 33172d586421SSepherosa Ziehau !ifq_is_empty(&ifp0->if_snd)) 33189db4b353SSepherosa Ziehau if_devstart(ifp0); 33192d586421SSepherosa Ziehau if (ifp1 != NULL && (ifp1->if_flags & IFF_RUNNING) != 0 && 33202d586421SSepherosa Ziehau !ifq_is_empty(&ifp1->if_snd)) 33219db4b353SSepherosa Ziehau if_devstart(ifp1); 33222d586421SSepherosa Ziehau } 33232d586421SSepherosa Ziehau 33242d586421SSepherosa Ziehau static void 3325d9e919c4SSepherosa Ziehau msk_set_tx_stfwd(struct msk_if_softc *sc_if) 3326d9e919c4SSepherosa Ziehau { 3327d9e919c4SSepherosa Ziehau struct msk_softc *sc = sc_if->msk_softc; 3328d9e919c4SSepherosa Ziehau struct ifnet *ifp = sc_if->msk_ifp; 3329d9e919c4SSepherosa Ziehau 33307b7b65f4SSepherosa Ziehau if ((sc->msk_hw_id == CHIP_ID_YUKON_EX && 33317b7b65f4SSepherosa Ziehau sc->msk_hw_rev != CHIP_REV_YU_EX_A0) || 33327b7b65f4SSepherosa Ziehau sc->msk_hw_id >= CHIP_ID_YUKON_SUPR) { 33337b7b65f4SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), 33347b7b65f4SSepherosa Ziehau TX_STFW_ENA); 3335d9e919c4SSepherosa Ziehau } else { 3336d9e919c4SSepherosa Ziehau if (ifp->if_mtu > ETHERMTU) { 3337d9e919c4SSepherosa Ziehau /* Set Tx GMAC FIFO Almost Empty Threshold. */ 3338d9e919c4SSepherosa Ziehau CSR_WRITE_4(sc, 3339d9e919c4SSepherosa Ziehau MR_ADDR(sc_if->msk_port, TX_GMF_AE_THR), 3340d9e919c4SSepherosa Ziehau MSK_ECU_JUMBO_WM << 16 | MSK_ECU_AE_THR); 3341d9e919c4SSepherosa Ziehau /* Disable Store & Forward mode for Tx. */ 33427b7b65f4SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), 33437b7b65f4SSepherosa Ziehau TX_STFW_DIS); 3344d9e919c4SSepherosa Ziehau } else { 33457b7b65f4SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), 33467b7b65f4SSepherosa Ziehau TX_STFW_ENA); 3347d9e919c4SSepherosa Ziehau } 3348d9e919c4SSepherosa Ziehau } 3349d9e919c4SSepherosa Ziehau } 3350d9e919c4SSepherosa Ziehau 3351d9e919c4SSepherosa Ziehau static void 33522d586421SSepherosa Ziehau msk_init(void *xsc) 33532d586421SSepherosa Ziehau { 33542d586421SSepherosa Ziehau struct msk_if_softc *sc_if = xsc; 33552d586421SSepherosa Ziehau struct msk_softc *sc = sc_if->msk_softc; 33562d586421SSepherosa Ziehau struct ifnet *ifp = sc_if->msk_ifp; 33572d586421SSepherosa Ziehau struct mii_data *mii; 33582d586421SSepherosa Ziehau uint16_t eaddr[ETHER_ADDR_LEN / 2]; 33592d586421SSepherosa Ziehau uint16_t gmac; 3360080bd27eSSepherosa Ziehau uint32_t reg; 33612d586421SSepherosa Ziehau int error, i; 33622d586421SSepherosa Ziehau 33632d586421SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 33642d586421SSepherosa Ziehau 33652d586421SSepherosa Ziehau mii = device_get_softc(sc_if->msk_miibus); 33662d586421SSepherosa Ziehau 33672d586421SSepherosa Ziehau error = 0; 33682d586421SSepherosa Ziehau /* Cancel pending I/O and free all Rx/Tx buffers. */ 33692d586421SSepherosa Ziehau msk_stop(sc_if); 33702d586421SSepherosa Ziehau 33712d586421SSepherosa Ziehau sc_if->msk_framesize = ifp->if_mtu + ETHER_HDR_LEN + EVL_ENCAPLEN; 33722d586421SSepherosa Ziehau if (sc_if->msk_framesize > MSK_MAX_FRAMELEN && 33732d586421SSepherosa Ziehau sc_if->msk_softc->msk_hw_id == CHIP_ID_YUKON_EC_U) { 33742d586421SSepherosa Ziehau /* 33752d586421SSepherosa Ziehau * In Yukon EC Ultra, TSO & checksum offload is not 33762d586421SSepherosa Ziehau * supported for jumbo frame. 33772d586421SSepherosa Ziehau */ 33782d586421SSepherosa Ziehau ifp->if_hwassist &= ~MSK_CSUM_FEATURES; 33792d586421SSepherosa Ziehau ifp->if_capenable &= ~IFCAP_TXCSUM; 33802d586421SSepherosa Ziehau } 33812d586421SSepherosa Ziehau 338255223f24SSepherosa Ziehau /* GMAC Control reset. */ 338355223f24SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_RST_SET); 338455223f24SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_RST_CLR); 338555223f24SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_F_LOOPB_OFF); 33860d557164SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_EX || 33870d557164SSepherosa Ziehau sc->msk_hw_id == CHIP_ID_YUKON_SUPR) { 3388d9e919c4SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), 3389d9e919c4SSepherosa Ziehau GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON | 3390d9e919c4SSepherosa Ziehau GMC_BYP_RETR_ON); 3391d9e919c4SSepherosa Ziehau } 339255223f24SSepherosa Ziehau 33932d586421SSepherosa Ziehau /* 339455223f24SSepherosa Ziehau * Initialize GMAC first such that speed/duplex/flow-control 339555223f24SSepherosa Ziehau * parameters are renegotiated when interface is brought up. 33962d586421SSepherosa Ziehau */ 339755223f24SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, 0); 33982d586421SSepherosa Ziehau 33992d586421SSepherosa Ziehau /* Dummy read the Interrupt Source Register. */ 34002d586421SSepherosa Ziehau CSR_READ_1(sc, MR_ADDR(sc_if->msk_port, GMAC_IRQ_SRC)); 34012d586421SSepherosa Ziehau 34022d586421SSepherosa Ziehau /* Set MIB Clear Counter Mode. */ 34032d586421SSepherosa Ziehau gmac = GMAC_READ_2(sc, sc_if->msk_port, GM_PHY_ADDR); 34042d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_PHY_ADDR, gmac | GM_PAR_MIB_CLR); 34052d586421SSepherosa Ziehau /* Read all MIB Counters with Clear Mode set. */ 34062d586421SSepherosa Ziehau for (i = 0; i < GM_MIB_CNT_SIZE; i++) 34072d586421SSepherosa Ziehau GMAC_READ_2(sc, sc_if->msk_port, GM_MIB_CNT_BASE + 8 * i); 34082d586421SSepherosa Ziehau /* Clear MIB Clear Counter Mode. */ 34092d586421SSepherosa Ziehau gmac &= ~GM_PAR_MIB_CLR; 34102d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_PHY_ADDR, gmac); 34112d586421SSepherosa Ziehau 34122d586421SSepherosa Ziehau /* Disable FCS. */ 34132d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_RX_CTRL, GM_RXCR_CRC_DIS); 34142d586421SSepherosa Ziehau 34152d586421SSepherosa Ziehau /* Setup Transmit Control Register. */ 34162d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF)); 34172d586421SSepherosa Ziehau 34182d586421SSepherosa Ziehau /* Setup Transmit Flow Control Register. */ 34192d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_TX_FLOW_CTRL, 0xffff); 34202d586421SSepherosa Ziehau 34212d586421SSepherosa Ziehau /* Setup Transmit Parameter Register. */ 34222d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_TX_PARAM, 34232d586421SSepherosa Ziehau TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) | TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) | 34242d586421SSepherosa Ziehau TX_IPG_JAM_DATA(TX_IPG_JAM_DEF) | TX_BACK_OFF_LIM(TX_BOF_LIM_DEF)); 34252d586421SSepherosa Ziehau 34262d586421SSepherosa Ziehau gmac = DATA_BLIND_VAL(DATA_BLIND_DEF) | 34272d586421SSepherosa Ziehau GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF); 34282d586421SSepherosa Ziehau 34292d586421SSepherosa Ziehau if (sc_if->msk_framesize > MSK_MAX_FRAMELEN) 34302d586421SSepherosa Ziehau gmac |= GM_SMOD_JUMBO_ENA; 34312d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_SERIAL_MODE, gmac); 34322d586421SSepherosa Ziehau 34332d586421SSepherosa Ziehau /* Set station address. */ 34342d586421SSepherosa Ziehau bcopy(IF_LLADDR(ifp), eaddr, ETHER_ADDR_LEN); 34352d586421SSepherosa Ziehau for (i = 0; i < ETHER_ADDR_LEN /2; i++) 34362d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_SRC_ADDR_1L + i * 4, 34372d586421SSepherosa Ziehau eaddr[i]); 34382d586421SSepherosa Ziehau for (i = 0; i < ETHER_ADDR_LEN /2; i++) 34392d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_SRC_ADDR_2L + i * 4, 34402d586421SSepherosa Ziehau eaddr[i]); 34412d586421SSepherosa Ziehau 34422d586421SSepherosa Ziehau /* Disable interrupts for counter overflows. */ 34432d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_TX_IRQ_MSK, 0); 34442d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_RX_IRQ_MSK, 0); 34452d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_TR_IRQ_MSK, 0); 34462d586421SSepherosa Ziehau 34472d586421SSepherosa Ziehau /* Configure Rx MAC FIFO. */ 34482d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), GMF_RST_SET); 34492d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), GMF_RST_CLR); 3450080bd27eSSepherosa Ziehau reg = GMF_OPER_ON | GMF_RX_F_FL_ON; 3451d9e919c4SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_FE_P || 3452d9e919c4SSepherosa Ziehau sc->msk_hw_id == CHIP_ID_YUKON_EX) 3453080bd27eSSepherosa Ziehau reg |= GMF_RX_OVER_ON; 3454080bd27eSSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), reg); 34552d586421SSepherosa Ziehau 3456dc7303ffSSepherosa Ziehau /* Set receive filter. */ 3457dc7303ffSSepherosa Ziehau msk_rxfilter(sc_if); 34582d586421SSepherosa Ziehau 345910cc281dSSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_XL) { 346010cc281dSSepherosa Ziehau /* Clear flush mask - HW bug. */ 346110cc281dSSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_FL_MSK), 0); 346210cc281dSSepherosa Ziehau } else { 34632d586421SSepherosa Ziehau /* Flush Rx MAC FIFO on any flow control or error. */ 34642d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_FL_MSK), 34652d586421SSepherosa Ziehau GMR_FS_ANY_ERR); 346610cc281dSSepherosa Ziehau } 34672d586421SSepherosa Ziehau 34688510fba4SSepherosa Ziehau /* 34698510fba4SSepherosa Ziehau * Set Rx FIFO flush threshold to 64 bytes 1 FIFO word 34708510fba4SSepherosa Ziehau * due to hardware hang on receipt of pause frames. 34718510fba4SSepherosa Ziehau */ 3472080bd27eSSepherosa Ziehau reg = RX_GMF_FL_THR_DEF + 1; 3473080bd27eSSepherosa Ziehau /* Another magic for Yukon FE+ - From Linux. */ 3474080bd27eSSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_FE_P && 3475080bd27eSSepherosa Ziehau sc->msk_hw_rev == CHIP_REV_YU_FE_P_A0) 3476080bd27eSSepherosa Ziehau reg = 0x178; 3477080bd27eSSepherosa Ziehau CSR_WRITE_2(sc, MR_ADDR(sc_if->msk_port, RX_GMF_FL_THR), reg); 3478080bd27eSSepherosa Ziehau 34792d586421SSepherosa Ziehau 34802d586421SSepherosa Ziehau /* Configure Tx MAC FIFO. */ 34812d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), GMF_RST_SET); 34822d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), GMF_RST_CLR); 34832d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), GMF_OPER_ON); 34842d586421SSepherosa Ziehau 34852d586421SSepherosa Ziehau /* Configure hardware VLAN tag insertion/stripping. */ 34862d586421SSepherosa Ziehau msk_setvlan(sc_if, ifp); 34872d586421SSepherosa Ziehau 34882a9b20a4SSepherosa Ziehau if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0) { 34892d586421SSepherosa Ziehau /* Set Rx Pause threshould. */ 3490ab5e50d3SSepherosa Ziehau CSR_WRITE_2(sc, MR_ADDR(sc_if->msk_port, RX_GMF_LP_THR), 34912d586421SSepherosa Ziehau MSK_ECU_LLPP); 3492ab5e50d3SSepherosa Ziehau CSR_WRITE_2(sc, MR_ADDR(sc_if->msk_port, RX_GMF_UP_THR), 34932d586421SSepherosa Ziehau MSK_ECU_ULPP); 3494d9e919c4SSepherosa Ziehau /* Configure store-and-forward for Tx. */ 3495d9e919c4SSepherosa Ziehau msk_set_tx_stfwd(sc_if); 34962d586421SSepherosa Ziehau } 34972d586421SSepherosa Ziehau 3498080bd27eSSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_FE_P && 3499080bd27eSSepherosa Ziehau sc->msk_hw_rev == CHIP_REV_YU_FE_P_A0) { 3500080bd27eSSepherosa Ziehau /* Disable dynamic watermark - from Linux. */ 3501080bd27eSSepherosa Ziehau reg = CSR_READ_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_EA)); 3502080bd27eSSepherosa Ziehau reg &= ~0x03; 3503080bd27eSSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_EA), reg); 3504080bd27eSSepherosa Ziehau } 3505080bd27eSSepherosa Ziehau 35062d586421SSepherosa Ziehau /* 35072d586421SSepherosa Ziehau * Disable Force Sync bit and Alloc bit in Tx RAM interface 35082d586421SSepherosa Ziehau * arbiter as we don't use Sync Tx queue. 35092d586421SSepherosa Ziehau */ 35102d586421SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, TXA_CTRL), 35112d586421SSepherosa Ziehau TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); 35122d586421SSepherosa Ziehau /* Enable the RAM Interface Arbiter. */ 35132d586421SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, TXA_CTRL), TXA_ENA_ARB); 35142d586421SSepherosa Ziehau 35152d586421SSepherosa Ziehau /* Setup RAM buffer. */ 35162d586421SSepherosa Ziehau msk_set_rambuffer(sc_if); 35172d586421SSepherosa Ziehau 35182d586421SSepherosa Ziehau /* Disable Tx sync Queue. */ 35192d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_txsq, RB_CTRL), RB_RST_SET); 35202d586421SSepherosa Ziehau 35212d586421SSepherosa Ziehau /* Setup Tx Queue Bus Memory Interface. */ 35222d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), BMU_CLR_RESET); 35232d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), BMU_OPER_INIT); 35242d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), BMU_FIFO_OP_ON); 35252d586421SSepherosa Ziehau CSR_WRITE_2(sc, Q_ADDR(sc_if->msk_txq, Q_WM), MSK_BMU_TX_WM); 3526d9e919c4SSepherosa Ziehau switch (sc->msk_hw_id) { 3527d9e919c4SSepherosa Ziehau case CHIP_ID_YUKON_EC_U: 3528d9e919c4SSepherosa Ziehau if (sc->msk_hw_rev == CHIP_REV_YU_EC_U_A0) { 35292d586421SSepherosa Ziehau /* Fix for Yukon-EC Ultra: set BMU FIFO level */ 3530d9e919c4SSepherosa Ziehau CSR_WRITE_2(sc, Q_ADDR(sc_if->msk_txq, Q_AL), 3531d9e919c4SSepherosa Ziehau MSK_ECU_TXFF_LEV); 3532d9e919c4SSepherosa Ziehau } 3533d9e919c4SSepherosa Ziehau break; 3534d9e919c4SSepherosa Ziehau case CHIP_ID_YUKON_EX: 3535d9e919c4SSepherosa Ziehau /* 3536d9e919c4SSepherosa Ziehau * Yukon Extreme seems to have silicon bug for 3537d9e919c4SSepherosa Ziehau * automatic Tx checksum calculation capability. 3538d9e919c4SSepherosa Ziehau */ 3539d9e919c4SSepherosa Ziehau if (sc->msk_hw_rev == CHIP_REV_YU_EX_B0) { 3540d9e919c4SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_F), 3541d9e919c4SSepherosa Ziehau F_TX_CHK_AUTO_OFF); 3542d9e919c4SSepherosa Ziehau } 3543d9e919c4SSepherosa Ziehau break; 35442d586421SSepherosa Ziehau } 35452d586421SSepherosa Ziehau 35462d586421SSepherosa Ziehau /* Setup Rx Queue Bus Memory Interface. */ 35472d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_CSR), BMU_CLR_RESET); 35482d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_CSR), BMU_OPER_INIT); 35492d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_CSR), BMU_FIFO_OP_ON); 35502d586421SSepherosa Ziehau CSR_WRITE_2(sc, Q_ADDR(sc_if->msk_rxq, Q_WM), MSK_BMU_RX_WM); 35512d586421SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_EC_U && 35522d586421SSepherosa Ziehau sc->msk_hw_rev >= CHIP_REV_YU_EC_U_A1) { 35532d586421SSepherosa Ziehau /* MAC Rx RAM Read is controlled by hardware. */ 35542d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_F), F_M_RX_RAM_DIS); 35552d586421SSepherosa Ziehau } 35562d586421SSepherosa Ziehau 35572d586421SSepherosa Ziehau msk_set_prefetch(sc, sc_if->msk_txq, 35582d586421SSepherosa Ziehau sc_if->msk_rdata.msk_tx_ring_paddr, MSK_TX_RING_CNT - 1); 35592d586421SSepherosa Ziehau msk_init_tx_ring(sc_if); 35602d586421SSepherosa Ziehau 35612d586421SSepherosa Ziehau /* Disable Rx checksum offload and RSS hash. */ 35622d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_CSR), 35632d586421SSepherosa Ziehau BMU_DIS_RX_CHKSUM | BMU_DIS_RX_RSS_HASH); 35642d586421SSepherosa Ziehau #ifdef MSK_JUMBO 35652d586421SSepherosa Ziehau if (sc_if->msk_framesize > (MCLBYTES - ETHER_HDR_LEN)) { 35662d586421SSepherosa Ziehau msk_set_prefetch(sc, sc_if->msk_rxq, 35672d586421SSepherosa Ziehau sc_if->msk_rdata.msk_jumbo_rx_ring_paddr, 35682d586421SSepherosa Ziehau MSK_JUMBO_RX_RING_CNT - 1); 35692d586421SSepherosa Ziehau error = msk_init_jumbo_rx_ring(sc_if); 35702d586421SSepherosa Ziehau } else 35712d586421SSepherosa Ziehau #endif 35722d586421SSepherosa Ziehau { 35732d586421SSepherosa Ziehau msk_set_prefetch(sc, sc_if->msk_rxq, 35742d586421SSepherosa Ziehau sc_if->msk_rdata.msk_rx_ring_paddr, 35752d586421SSepherosa Ziehau MSK_RX_RING_CNT - 1); 35762d586421SSepherosa Ziehau error = msk_init_rx_ring(sc_if); 35772d586421SSepherosa Ziehau } 35782d586421SSepherosa Ziehau if (error != 0) { 35792d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, 35802d586421SSepherosa Ziehau "initialization failed: no memory for Rx buffers\n"); 35812d586421SSepherosa Ziehau msk_stop(sc_if); 35822d586421SSepherosa Ziehau return; 35832d586421SSepherosa Ziehau } 35840d557164SSepherosa Ziehau if (sc->msk_hw_id == CHIP_ID_YUKON_EX || 35850d557164SSepherosa Ziehau sc->msk_hw_id == CHIP_ID_YUKON_SUPR) { 3586441c9e87SSepherosa Ziehau /* Disable flushing of non-ASF packets. */ 3587441c9e87SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), 3588441c9e87SSepherosa Ziehau GMF_RX_MACSEC_FLUSH_OFF); 3589441c9e87SSepherosa Ziehau } 35902d586421SSepherosa Ziehau 35912d586421SSepherosa Ziehau /* Configure interrupt handling. */ 35922d586421SSepherosa Ziehau if (sc_if->msk_port == MSK_PORT_A) { 35932d586421SSepherosa Ziehau sc->msk_intrmask |= Y2_IS_PORT_A; 35942d586421SSepherosa Ziehau sc->msk_intrhwemask |= Y2_HWE_L1_MASK; 35952d586421SSepherosa Ziehau } else { 35962d586421SSepherosa Ziehau sc->msk_intrmask |= Y2_IS_PORT_B; 35972d586421SSepherosa Ziehau sc->msk_intrhwemask |= Y2_HWE_L2_MASK; 35982d586421SSepherosa Ziehau } 35992d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_HWE_IMSK, sc->msk_intrhwemask); 36002d586421SSepherosa Ziehau CSR_READ_4(sc, B0_HWE_IMSK); 36012d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, sc->msk_intrmask); 36022d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 36032d586421SSepherosa Ziehau 36042d586421SSepherosa Ziehau sc_if->msk_link = 0; 36052d586421SSepherosa Ziehau mii_mediachg(mii); 36062d586421SSepherosa Ziehau 3607f59f1081SSepherosa Ziehau mskc_set_imtimer(sc); 3608f59f1081SSepherosa Ziehau 36092d586421SSepherosa Ziehau ifp->if_flags |= IFF_RUNNING; 3610*9ed293e0SSepherosa Ziehau ifq_clr_oactive(&ifp->if_snd); 36112d586421SSepherosa Ziehau 36122d586421SSepherosa Ziehau callout_reset(&sc_if->msk_tick_ch, hz, msk_tick, sc_if); 36132d586421SSepherosa Ziehau } 36142d586421SSepherosa Ziehau 36152d586421SSepherosa Ziehau static void 36162d586421SSepherosa Ziehau msk_set_rambuffer(struct msk_if_softc *sc_if) 36172d586421SSepherosa Ziehau { 36182d586421SSepherosa Ziehau struct msk_softc *sc; 36192d586421SSepherosa Ziehau int ltpp, utpp; 36202d586421SSepherosa Ziehau 36212a9b20a4SSepherosa Ziehau if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0) 36222a9b20a4SSepherosa Ziehau return; 36232a9b20a4SSepherosa Ziehau 36242d586421SSepherosa Ziehau sc = sc_if->msk_softc; 36252d586421SSepherosa Ziehau 36262d586421SSepherosa Ziehau /* Setup Rx Queue. */ 36272d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_rxq, RB_CTRL), RB_RST_CLR); 36282d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_rxq, RB_START), 36292d586421SSepherosa Ziehau sc->msk_rxqstart[sc_if->msk_port] / 8); 36302d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_rxq, RB_END), 36312d586421SSepherosa Ziehau sc->msk_rxqend[sc_if->msk_port] / 8); 36322d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_rxq, RB_WP), 36332d586421SSepherosa Ziehau sc->msk_rxqstart[sc_if->msk_port] / 8); 36342d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_rxq, RB_RP), 36352d586421SSepherosa Ziehau sc->msk_rxqstart[sc_if->msk_port] / 8); 36362d586421SSepherosa Ziehau 36372d586421SSepherosa Ziehau utpp = (sc->msk_rxqend[sc_if->msk_port] + 1 - 36382d586421SSepherosa Ziehau sc->msk_rxqstart[sc_if->msk_port] - MSK_RB_ULPP) / 8; 36392d586421SSepherosa Ziehau ltpp = (sc->msk_rxqend[sc_if->msk_port] + 1 - 36402d586421SSepherosa Ziehau sc->msk_rxqstart[sc_if->msk_port] - MSK_RB_LLPP_B) / 8; 36412d586421SSepherosa Ziehau if (sc->msk_rxqsize < MSK_MIN_RXQ_SIZE) 36422d586421SSepherosa Ziehau ltpp += (MSK_RB_LLPP_B - MSK_RB_LLPP_S) / 8; 36432d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_rxq, RB_RX_UTPP), utpp); 36442d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_rxq, RB_RX_LTPP), ltpp); 36452d586421SSepherosa Ziehau /* Set Rx priority(RB_RX_UTHP/RB_RX_LTHP) thresholds? */ 36462d586421SSepherosa Ziehau 36472d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_rxq, RB_CTRL), RB_ENA_OP_MD); 36482d586421SSepherosa Ziehau CSR_READ_1(sc, RB_ADDR(sc_if->msk_rxq, RB_CTRL)); 36492d586421SSepherosa Ziehau 36502d586421SSepherosa Ziehau /* Setup Tx Queue. */ 36512d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_txq, RB_CTRL), RB_RST_CLR); 36522d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_txq, RB_START), 36532d586421SSepherosa Ziehau sc->msk_txqstart[sc_if->msk_port] / 8); 36542d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_txq, RB_END), 36552d586421SSepherosa Ziehau sc->msk_txqend[sc_if->msk_port] / 8); 36562d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_txq, RB_WP), 36572d586421SSepherosa Ziehau sc->msk_txqstart[sc_if->msk_port] / 8); 36582d586421SSepherosa Ziehau CSR_WRITE_4(sc, RB_ADDR(sc_if->msk_txq, RB_RP), 36592d586421SSepherosa Ziehau sc->msk_txqstart[sc_if->msk_port] / 8); 36602d586421SSepherosa Ziehau /* Enable Store & Forward for Tx side. */ 36612d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_txq, RB_CTRL), RB_ENA_STFWD); 36622d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_txq, RB_CTRL), RB_ENA_OP_MD); 36632d586421SSepherosa Ziehau CSR_READ_1(sc, RB_ADDR(sc_if->msk_txq, RB_CTRL)); 36642d586421SSepherosa Ziehau } 36652d586421SSepherosa Ziehau 36662d586421SSepherosa Ziehau static void 36672d586421SSepherosa Ziehau msk_set_prefetch(struct msk_softc *sc, int qaddr, bus_addr_t addr, 36682d586421SSepherosa Ziehau uint32_t count) 36692d586421SSepherosa Ziehau { 36702d586421SSepherosa Ziehau 36712d586421SSepherosa Ziehau /* Reset the prefetch unit. */ 36722d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_CTRL_REG), 36732d586421SSepherosa Ziehau PREF_UNIT_RST_SET); 36742d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_CTRL_REG), 36752d586421SSepherosa Ziehau PREF_UNIT_RST_CLR); 36762d586421SSepherosa Ziehau /* Set LE base address. */ 36772d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_ADDR_LOW_REG), 36782d586421SSepherosa Ziehau MSK_ADDR_LO(addr)); 36792d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_ADDR_HI_REG), 36802d586421SSepherosa Ziehau MSK_ADDR_HI(addr)); 36812d586421SSepherosa Ziehau /* Set the list last index. */ 36822d586421SSepherosa Ziehau CSR_WRITE_2(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_LAST_IDX_REG), 36832d586421SSepherosa Ziehau count); 36842d586421SSepherosa Ziehau /* Turn on prefetch unit. */ 36852d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_CTRL_REG), 36862d586421SSepherosa Ziehau PREF_UNIT_OP_ON); 36872d586421SSepherosa Ziehau /* Dummy read to ensure write. */ 36882d586421SSepherosa Ziehau CSR_READ_4(sc, Y2_PREF_Q_ADDR(qaddr, PREF_UNIT_CTRL_REG)); 36892d586421SSepherosa Ziehau } 36902d586421SSepherosa Ziehau 36912d586421SSepherosa Ziehau static void 36922d586421SSepherosa Ziehau msk_stop(struct msk_if_softc *sc_if) 36932d586421SSepherosa Ziehau { 36942d586421SSepherosa Ziehau struct msk_softc *sc = sc_if->msk_softc; 36952d586421SSepherosa Ziehau struct ifnet *ifp = sc_if->msk_ifp; 36962d586421SSepherosa Ziehau struct msk_txdesc *txd; 36972d586421SSepherosa Ziehau struct msk_rxdesc *rxd; 36982d586421SSepherosa Ziehau #ifdef MSK_JUMBO 36992d586421SSepherosa Ziehau struct msk_rxdesc *jrxd; 37002d586421SSepherosa Ziehau #endif 37012d586421SSepherosa Ziehau uint32_t val; 37022d586421SSepherosa Ziehau int i; 37032d586421SSepherosa Ziehau 37042d586421SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 37052d586421SSepherosa Ziehau 37062d586421SSepherosa Ziehau callout_stop(&sc_if->msk_tick_ch); 37072d586421SSepherosa Ziehau ifp->if_timer = 0; 37082d586421SSepherosa Ziehau 37092d586421SSepherosa Ziehau /* Disable interrupts. */ 37102d586421SSepherosa Ziehau if (sc_if->msk_port == MSK_PORT_A) { 37112d586421SSepherosa Ziehau sc->msk_intrmask &= ~Y2_IS_PORT_A; 37122d586421SSepherosa Ziehau sc->msk_intrhwemask &= ~Y2_HWE_L1_MASK; 37132d586421SSepherosa Ziehau } else { 37142d586421SSepherosa Ziehau sc->msk_intrmask &= ~Y2_IS_PORT_B; 37152d586421SSepherosa Ziehau sc->msk_intrhwemask &= ~Y2_HWE_L2_MASK; 37162d586421SSepherosa Ziehau } 37172d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_HWE_IMSK, sc->msk_intrhwemask); 37182d586421SSepherosa Ziehau CSR_READ_4(sc, B0_HWE_IMSK); 37192d586421SSepherosa Ziehau CSR_WRITE_4(sc, B0_IMSK, sc->msk_intrmask); 37202d586421SSepherosa Ziehau CSR_READ_4(sc, B0_IMSK); 37212d586421SSepherosa Ziehau 37222d586421SSepherosa Ziehau /* Disable Tx/Rx MAC. */ 37232d586421SSepherosa Ziehau val = GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL); 37242d586421SSepherosa Ziehau val &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); 37252d586421SSepherosa Ziehau GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, val); 37262d586421SSepherosa Ziehau /* Read again to ensure writing. */ 37272d586421SSepherosa Ziehau GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL); 37282d586421SSepherosa Ziehau 37292d586421SSepherosa Ziehau /* Stop Tx BMU. */ 37302d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), BMU_STOP); 37312d586421SSepherosa Ziehau val = CSR_READ_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR)); 37322d586421SSepherosa Ziehau for (i = 0; i < MSK_TIMEOUT; i++) { 37332d586421SSepherosa Ziehau if ((val & (BMU_STOP | BMU_IDLE)) == 0) { 37342d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), 37352d586421SSepherosa Ziehau BMU_STOP); 373669853fa0SSepherosa Ziehau val = CSR_READ_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR)); 37372d586421SSepherosa Ziehau } else 37382d586421SSepherosa Ziehau break; 37392d586421SSepherosa Ziehau DELAY(1); 37402d586421SSepherosa Ziehau } 37412d586421SSepherosa Ziehau if (i == MSK_TIMEOUT) 37422d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "Tx BMU stop failed\n"); 37432d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_txq, RB_CTRL), 37442d586421SSepherosa Ziehau RB_RST_SET | RB_DIS_OP_MD); 37452d586421SSepherosa Ziehau 37462d586421SSepherosa Ziehau /* Disable all GMAC interrupt. */ 37472d586421SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, GMAC_IRQ_MSK), 0); 37482d586421SSepherosa Ziehau /* Disable PHY interrupt. */ 37492d586421SSepherosa Ziehau msk_phy_writereg(sc_if, PHY_ADDR_MARV, PHY_MARV_INT_MASK, 0); 37502d586421SSepherosa Ziehau 37512d586421SSepherosa Ziehau /* Disable the RAM Interface Arbiter. */ 37522d586421SSepherosa Ziehau CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, TXA_CTRL), TXA_DIS_ARB); 37532d586421SSepherosa Ziehau 37542d586421SSepherosa Ziehau /* Reset the PCI FIFO of the async Tx queue */ 37552d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_txq, Q_CSR), 37562d586421SSepherosa Ziehau BMU_RST_SET | BMU_FIFO_RST); 37572d586421SSepherosa Ziehau 37582d586421SSepherosa Ziehau /* Reset the Tx prefetch units. */ 37592d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(sc_if->msk_txq, PREF_UNIT_CTRL_REG), 37602d586421SSepherosa Ziehau PREF_UNIT_RST_SET); 37612d586421SSepherosa Ziehau 37622d586421SSepherosa Ziehau /* Reset the RAM Buffer async Tx queue. */ 37632d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_txq, RB_CTRL), RB_RST_SET); 37642d586421SSepherosa Ziehau 37652d586421SSepherosa Ziehau /* Reset Tx MAC FIFO. */ 37662d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, TX_GMF_CTRL_T), GMF_RST_SET); 37672d586421SSepherosa Ziehau /* Set Pause Off. */ 37682d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, GMAC_CTRL), GMC_PAUSE_OFF); 37692d586421SSepherosa Ziehau 37702d586421SSepherosa Ziehau /* 37712d586421SSepherosa Ziehau * The Rx Stop command will not work for Yukon-2 if the BMU does not 37722d586421SSepherosa Ziehau * reach the end of packet and since we can't make sure that we have 37732d586421SSepherosa Ziehau * incoming data, we must reset the BMU while it is not during a DMA 37742d586421SSepherosa Ziehau * transfer. Since it is possible that the Rx path is still active, 37752d586421SSepherosa Ziehau * the Rx RAM buffer will be stopped first, so any possible incoming 37762d586421SSepherosa Ziehau * data will not trigger a DMA. After the RAM buffer is stopped, the 37772d586421SSepherosa Ziehau * BMU is polled until any DMA in progress is ended and only then it 37782d586421SSepherosa Ziehau * will be reset. 37792d586421SSepherosa Ziehau */ 37802d586421SSepherosa Ziehau 37812d586421SSepherosa Ziehau /* Disable the RAM Buffer receive queue. */ 37822d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_rxq, RB_CTRL), RB_DIS_OP_MD); 37832d586421SSepherosa Ziehau for (i = 0; i < MSK_TIMEOUT; i++) { 37842d586421SSepherosa Ziehau if (CSR_READ_1(sc, RB_ADDR(sc_if->msk_rxq, Q_RSL)) == 37852d586421SSepherosa Ziehau CSR_READ_1(sc, RB_ADDR(sc_if->msk_rxq, Q_RL))) 37862d586421SSepherosa Ziehau break; 37872d586421SSepherosa Ziehau DELAY(1); 37882d586421SSepherosa Ziehau } 37892d586421SSepherosa Ziehau if (i == MSK_TIMEOUT) 37902d586421SSepherosa Ziehau device_printf(sc_if->msk_if_dev, "Rx BMU stop failed\n"); 37912d586421SSepherosa Ziehau CSR_WRITE_4(sc, Q_ADDR(sc_if->msk_rxq, Q_CSR), 37922d586421SSepherosa Ziehau BMU_RST_SET | BMU_FIFO_RST); 37932d586421SSepherosa Ziehau /* Reset the Rx prefetch unit. */ 37942d586421SSepherosa Ziehau CSR_WRITE_4(sc, Y2_PREF_Q_ADDR(sc_if->msk_rxq, PREF_UNIT_CTRL_REG), 37952d586421SSepherosa Ziehau PREF_UNIT_RST_SET); 37962d586421SSepherosa Ziehau /* Reset the RAM Buffer receive queue. */ 37972d586421SSepherosa Ziehau CSR_WRITE_1(sc, RB_ADDR(sc_if->msk_rxq, RB_CTRL), RB_RST_SET); 37982d586421SSepherosa Ziehau /* Reset Rx MAC FIFO. */ 37992d586421SSepherosa Ziehau CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), GMF_RST_SET); 38002d586421SSepherosa Ziehau 38012d586421SSepherosa Ziehau /* Free Rx and Tx mbufs still in the queues. */ 38022d586421SSepherosa Ziehau for (i = 0; i < MSK_RX_RING_CNT; i++) { 38032d586421SSepherosa Ziehau rxd = &sc_if->msk_cdata.msk_rxdesc[i]; 38042d586421SSepherosa Ziehau if (rxd->rx_m != NULL) { 38052d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_rx_tag, 38062d586421SSepherosa Ziehau rxd->rx_dmamap); 38072d586421SSepherosa Ziehau m_freem(rxd->rx_m); 38082d586421SSepherosa Ziehau rxd->rx_m = NULL; 38092d586421SSepherosa Ziehau } 38102d586421SSepherosa Ziehau } 38112d586421SSepherosa Ziehau #ifdef MSK_JUMBO 38122d586421SSepherosa Ziehau for (i = 0; i < MSK_JUMBO_RX_RING_CNT; i++) { 38132d586421SSepherosa Ziehau jrxd = &sc_if->msk_cdata.msk_jumbo_rxdesc[i]; 38142d586421SSepherosa Ziehau if (jrxd->rx_m != NULL) { 38152d586421SSepherosa Ziehau bus_dmamap_sync(sc_if->msk_cdata.msk_jumbo_rx_tag, 38162d586421SSepherosa Ziehau jrxd->rx_dmamap, BUS_DMASYNC_POSTREAD); 38172d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_jumbo_rx_tag, 38182d586421SSepherosa Ziehau jrxd->rx_dmamap); 38192d586421SSepherosa Ziehau m_freem(jrxd->rx_m); 38202d586421SSepherosa Ziehau jrxd->rx_m = NULL; 38212d586421SSepherosa Ziehau } 38222d586421SSepherosa Ziehau } 38232d586421SSepherosa Ziehau #endif 38242d586421SSepherosa Ziehau for (i = 0; i < MSK_TX_RING_CNT; i++) { 38252d586421SSepherosa Ziehau txd = &sc_if->msk_cdata.msk_txdesc[i]; 38262d586421SSepherosa Ziehau if (txd->tx_m != NULL) { 38272d586421SSepherosa Ziehau bus_dmamap_unload(sc_if->msk_cdata.msk_tx_tag, 38282d586421SSepherosa Ziehau txd->tx_dmamap); 38292d586421SSepherosa Ziehau m_freem(txd->tx_m); 38302d586421SSepherosa Ziehau txd->tx_m = NULL; 38312d586421SSepherosa Ziehau } 38322d586421SSepherosa Ziehau } 38332d586421SSepherosa Ziehau 38342d586421SSepherosa Ziehau /* 38352d586421SSepherosa Ziehau * Mark the interface down. 38362d586421SSepherosa Ziehau */ 3837*9ed293e0SSepherosa Ziehau ifp->if_flags &= ~IFF_RUNNING; 3838*9ed293e0SSepherosa Ziehau ifq_clr_oactive(&ifp->if_snd); 38392d586421SSepherosa Ziehau sc_if->msk_link = 0; 38402d586421SSepherosa Ziehau } 38412d586421SSepherosa Ziehau 38422d586421SSepherosa Ziehau static int 3843f59f1081SSepherosa Ziehau mskc_sysctl_proc_limit(SYSCTL_HANDLER_ARGS) 38442d586421SSepherosa Ziehau { 3845f59f1081SSepherosa Ziehau return sysctl_int_range(oidp, arg1, arg2, req, 3846f59f1081SSepherosa Ziehau MSK_PROC_MIN, MSK_PROC_MAX); 38472d586421SSepherosa Ziehau } 38482d586421SSepherosa Ziehau 3849f59f1081SSepherosa Ziehau static int 3850f59f1081SSepherosa Ziehau mskc_sysctl_intr_rate(SYSCTL_HANDLER_ARGS) 3851f59f1081SSepherosa Ziehau { 3852f59f1081SSepherosa Ziehau struct msk_softc *sc = arg1; 3853f59f1081SSepherosa Ziehau struct lwkt_serialize *serializer = &sc->msk_serializer; 3854f59f1081SSepherosa Ziehau int error = 0, v; 3855f59f1081SSepherosa Ziehau 3856f59f1081SSepherosa Ziehau lwkt_serialize_enter(serializer); 3857f59f1081SSepherosa Ziehau 3858f59f1081SSepherosa Ziehau v = sc->msk_intr_rate; 3859f59f1081SSepherosa Ziehau error = sysctl_handle_int(oidp, &v, 0, req); 3860f59f1081SSepherosa Ziehau if (error || req->newptr == NULL) 3861f59f1081SSepherosa Ziehau goto back; 3862f59f1081SSepherosa Ziehau if (v < 0) { 3863f59f1081SSepherosa Ziehau error = EINVAL; 3864f59f1081SSepherosa Ziehau goto back; 3865f59f1081SSepherosa Ziehau } 3866f59f1081SSepherosa Ziehau 3867f59f1081SSepherosa Ziehau if (sc->msk_intr_rate != v) { 3868f59f1081SSepherosa Ziehau int flag = 0, i; 3869f59f1081SSepherosa Ziehau 3870f59f1081SSepherosa Ziehau sc->msk_intr_rate = v; 3871f59f1081SSepherosa Ziehau for (i = 0; i < 2; ++i) { 3872f59f1081SSepherosa Ziehau if (sc->msk_if[i] != NULL) { 3873f59f1081SSepherosa Ziehau flag |= sc->msk_if[i]-> 3874f59f1081SSepherosa Ziehau arpcom.ac_if.if_flags & IFF_RUNNING; 3875f59f1081SSepherosa Ziehau } 3876f59f1081SSepherosa Ziehau } 3877f59f1081SSepherosa Ziehau if (flag) 3878f59f1081SSepherosa Ziehau mskc_set_imtimer(sc); 3879f59f1081SSepherosa Ziehau } 3880f59f1081SSepherosa Ziehau back: 3881f59f1081SSepherosa Ziehau lwkt_serialize_exit(serializer); 3882f59f1081SSepherosa Ziehau return error; 3883f59f1081SSepherosa Ziehau } 38842d586421SSepherosa Ziehau 38852d586421SSepherosa Ziehau static int 38862d586421SSepherosa Ziehau msk_dmamem_create(device_t dev, bus_size_t size, bus_dma_tag_t *dtag, 38872d586421SSepherosa Ziehau void **addr, bus_addr_t *paddr, bus_dmamap_t *dmap) 38882d586421SSepherosa Ziehau { 38892d586421SSepherosa Ziehau struct msk_if_softc *sc_if = device_get_softc(dev); 3890c78f83cbSSepherosa Ziehau bus_dmamem_t dmem; 38912d586421SSepherosa Ziehau int error; 38922d586421SSepherosa Ziehau 3893c78f83cbSSepherosa Ziehau error = bus_dmamem_coherent(sc_if->msk_cdata.msk_parent_tag, 38942d586421SSepherosa Ziehau MSK_RING_ALIGN, 0, 38952d586421SSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 3896c78f83cbSSepherosa Ziehau size, BUS_DMA_WAITOK | BUS_DMA_ZERO, &dmem); 38972d586421SSepherosa Ziehau if (error) { 3898c78f83cbSSepherosa Ziehau device_printf(dev, "can't create coherent DMA memory\n"); 38992d586421SSepherosa Ziehau return error; 39002d586421SSepherosa Ziehau } 39012d586421SSepherosa Ziehau 3902c78f83cbSSepherosa Ziehau *dtag = dmem.dmem_tag; 3903c78f83cbSSepherosa Ziehau *dmap = dmem.dmem_map; 3904c78f83cbSSepherosa Ziehau *addr = dmem.dmem_addr; 3905c78f83cbSSepherosa Ziehau *paddr = dmem.dmem_busaddr; 39062d586421SSepherosa Ziehau 39072d586421SSepherosa Ziehau return 0; 39082d586421SSepherosa Ziehau } 39092d586421SSepherosa Ziehau 39102d586421SSepherosa Ziehau static void 39112d586421SSepherosa Ziehau msk_dmamem_destroy(bus_dma_tag_t dtag, void *addr, bus_dmamap_t dmap) 39122d586421SSepherosa Ziehau { 39132d586421SSepherosa Ziehau if (dtag != NULL) { 39142d586421SSepherosa Ziehau bus_dmamap_unload(dtag, dmap); 39152d586421SSepherosa Ziehau bus_dmamem_free(dtag, addr, dmap); 39162d586421SSepherosa Ziehau bus_dma_tag_destroy(dtag); 39172d586421SSepherosa Ziehau } 39182d586421SSepherosa Ziehau } 3919f59f1081SSepherosa Ziehau 3920f59f1081SSepherosa Ziehau static void 3921f59f1081SSepherosa Ziehau mskc_set_imtimer(struct msk_softc *sc) 3922f59f1081SSepherosa Ziehau { 3923f59f1081SSepherosa Ziehau if (sc->msk_intr_rate > 0) { 3924f59f1081SSepherosa Ziehau /* 3925f59f1081SSepherosa Ziehau * XXX myk(4) seems to use 125MHz for EC/FE/XL 3926f59f1081SSepherosa Ziehau * and 78.125MHz for rest of chip types 3927f59f1081SSepherosa Ziehau */ 3928f59f1081SSepherosa Ziehau CSR_WRITE_4(sc, B2_IRQM_INI, 3929f59f1081SSepherosa Ziehau MSK_USECS(sc, 1000000 / sc->msk_intr_rate)); 3930f59f1081SSepherosa Ziehau CSR_WRITE_4(sc, B2_IRQM_MSK, sc->msk_intrmask); 3931f59f1081SSepherosa Ziehau CSR_WRITE_4(sc, B2_IRQM_CTRL, TIM_START); 3932f59f1081SSepherosa Ziehau } else { 3933f59f1081SSepherosa Ziehau CSR_WRITE_4(sc, B2_IRQM_CTRL, TIM_STOP); 3934f59f1081SSepherosa Ziehau } 3935f59f1081SSepherosa Ziehau } 3936